Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

Linux/drivers/media/usb/b2c2/flexcop-usb.c

  1 /*
  2  * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
  3  * flexcop-usb.c - covers the USB part
  4  * see flexcop.c for copyright information
  5  */
  6 #define FC_LOG_PREFIX "flexcop_usb"
  7 #include "flexcop-usb.h"
  8 #include "flexcop-common.h"
  9 
 10 /* Version information */
 11 #define DRIVER_VERSION "0.1"
 12 #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver"
 13 #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
 14 
 15 /* debug */
 16 #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
 17 #define dprintk(level,args...) \
 18         do { if ((debug & level)) printk(args); } while (0)
 19 
 20 #define debug_dump(b, l, method) do {\
 21         int i; \
 22         for (i = 0; i < l; i++) \
 23                 method("%02x ", b[i]); \
 24         method("\n"); \
 25 } while (0)
 26 
 27 #define DEBSTATUS ""
 28 #else
 29 #define dprintk(level, args...)
 30 #define debug_dump(b, l, method)
 31 #define DEBSTATUS " (debugging is not enabled)"
 32 #endif
 33 
 34 static int debug;
 35 module_param(debug, int, 0644);
 36 MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,"
 37                 "ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
 38 #undef DEBSTATUS
 39 
 40 #define deb_info(args...) dprintk(0x01, args)
 41 #define deb_ts(args...) dprintk(0x02, args)
 42 #define deb_ctrl(args...) dprintk(0x04, args)
 43 #define deb_i2c(args...) dprintk(0x08, args)
 44 #define deb_v8(args...) dprintk(0x10, args)
 45 
 46 /* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
 47  * in the IBI address, to make the V8 code simpler.
 48  * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (the six bits used)
 49  *                  in general: 0000 0HHH 000L LL00
 50  * IBI ADDRESS FORMAT:                    RHHH BLLL
 51  *
 52  * where R is the read(1)/write(0) bit, B is the busy bit
 53  * and HHH and LLL are the two sets of three bits from the PCI address.
 54  */
 55 #define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) \
 56         (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
 57 #define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) \
 58         (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
 59 
 60 /*
 61  * DKT 020228
 62  * - forget about this VENDOR_BUFFER_SIZE, read and write register
 63  *   deal with DWORD or 4 bytes, that should be should from now on
 64  * - from now on, we don't support anything older than firm 1.00
 65  *   I eliminated the write register as a 2 trip of writing hi word and lo word
 66  *   and force this to write only 4 bytes at a time.
 67  *   NOTE: this should work with all the firmware from 1.00 and newer
 68  */
 69 static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, u32 *val, u8 read)
 70 {
 71         struct flexcop_usb *fc_usb = fc->bus_specific;
 72         u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG;
 73         u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
 74         u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
 75                 (read ? 0x80 : 0);
 76 
 77         int len = usb_control_msg(fc_usb->udev,
 78                         read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
 79                         request,
 80                         request_type, /* 0xc0 read or 0x40 write */
 81                         wAddress,
 82                         0,
 83                         val,
 84                         sizeof(u32),
 85                         B2C2_WAIT_FOR_OPERATION_RDW * HZ);
 86 
 87         if (len != sizeof(u32)) {
 88                 err("error while %s dword from %d (%d).", read ? "reading" :
 89                                 "writing", wAddress, wRegOffsPCI);
 90                 return -EIO;
 91         }
 92         return 0;
 93 }
 94 /*
 95  * DKT 010817 - add support for V8 memory read/write and flash update
 96  */
 97 static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
 98                 flexcop_usb_request_t req, u8 page, u16 wAddress,
 99                 u8 *pbBuffer, u32 buflen)
100 {
101         u8 request_type = USB_TYPE_VENDOR;
102         u16 wIndex;
103         int nWaitTime, pipe, len;
104         wIndex = page << 8;
105 
106         switch (req) {
107         case B2C2_USB_READ_V8_MEM:
108                 nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
109                 request_type |= USB_DIR_IN;
110                 pipe = B2C2_USB_CTRL_PIPE_IN;
111                 break;
112         case B2C2_USB_WRITE_V8_MEM:
113                 wIndex |= pbBuffer[0];
114                 request_type |= USB_DIR_OUT;
115                 nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
116                 pipe = B2C2_USB_CTRL_PIPE_OUT;
117                 break;
118         case B2C2_USB_FLASH_BLOCK:
119                 request_type |= USB_DIR_OUT;
120                 nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
121                 pipe = B2C2_USB_CTRL_PIPE_OUT;
122                 break;
123         default:
124                 deb_info("unsupported request for v8_mem_req %x.\n", req);
125                 return -EINVAL;
126         }
127         deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
128                         wAddress, wIndex, buflen);
129 
130         len = usb_control_msg(fc_usb->udev, pipe,
131                         req,
132                         request_type,
133                         wAddress,
134                         wIndex,
135                         pbBuffer,
136                         buflen,
137                         nWaitTime * HZ);
138 
139         debug_dump(pbBuffer, len, deb_v8);
140         return len == buflen ? 0 : -EIO;
141 }
142 
143 #define bytes_left_to_read_on_page(paddr,buflen) \
144         ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \
145          ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)))
146 
147 static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,
148                 flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start,
149                 u32 addr, int extended, u8 *buf, u32 len)
150 {
151         int i,ret = 0;
152         u16 wMax;
153         u32 pagechunk = 0;
154 
155         switch(req) {
156         case B2C2_USB_READ_V8_MEM:
157                 wMax = USB_MEM_READ_MAX;
158                 break;
159         case B2C2_USB_WRITE_V8_MEM:
160                 wMax = USB_MEM_WRITE_MAX;
161                 break;
162         case B2C2_USB_FLASH_BLOCK:
163                 wMax = USB_FLASH_MAX;
164                 break;
165         default:
166                 return -EINVAL;
167                 break;
168         }
169         for (i = 0; i < len;) {
170                 pagechunk =
171                         wMax < bytes_left_to_read_on_page(addr, len) ?
172                                 wMax :
173                                 bytes_left_to_read_on_page(addr, len);
174                 deb_info("%x\n",
175                         (addr & V8_MEMORY_PAGE_MASK) |
176                                 (V8_MEMORY_EXTENDED*extended));
177 
178                 ret = flexcop_usb_v8_memory_req(fc_usb, req,
179                         page_start + (addr / V8_MEMORY_PAGE_SIZE),
180                         (addr & V8_MEMORY_PAGE_MASK) |
181                                 (V8_MEMORY_EXTENDED*extended),
182                         &buf[i], pagechunk);
183 
184                 if (ret < 0)
185                         return ret;
186                 addr += pagechunk;
187                 len -= pagechunk;
188         }
189         return 0;
190 }
191 
192 static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
193 {
194         return flexcop_usb_memory_req(fc->bus_specific, B2C2_USB_READ_V8_MEM,
195                 V8_MEMORY_PAGE_FLASH, 0x1f010, 1,
196                 fc->dvb_adapter.proposed_mac, 6);
197 }
198 
199 #if 0
200 static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
201                 flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
202                 u16 buflen, u8 *pvBuffer)
203 {
204         u16 wValue;
205         u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
206         int nWaitTime = 2,
207             pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
208         wValue = (func << 8) | extra;
209 
210         len = usb_control_msg(fc_usb->udev,pipe,
211                         B2C2_USB_UTILITY,
212                         request_type,
213                         wValue,
214                         wIndex,
215                         pvBuffer,
216                         buflen,
217                         nWaitTime * HZ);
218         return len == buflen ? 0 : -EIO;
219 }
220 #endif
221 
222 /* usb i2c stuff */
223 static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
224                 flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
225                 u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
226 {
227         struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
228         u16 wValue, wIndex;
229         int nWaitTime,pipe,len;
230         u8 request_type = USB_TYPE_VENDOR;
231 
232         switch (func) {
233         case USB_FUNC_I2C_WRITE:
234         case USB_FUNC_I2C_MULTIWRITE:
235         case USB_FUNC_I2C_REPEATWRITE:
236                 /* DKT 020208 - add this to support special case of DiSEqC */
237         case USB_FUNC_I2C_CHECKWRITE:
238                 pipe = B2C2_USB_CTRL_PIPE_OUT;
239                 nWaitTime = 2;
240                 request_type |= USB_DIR_OUT;
241                 break;
242         case USB_FUNC_I2C_READ:
243         case USB_FUNC_I2C_REPEATREAD:
244                 pipe = B2C2_USB_CTRL_PIPE_IN;
245                 nWaitTime = 2;
246                 request_type |= USB_DIR_IN;
247                 break;
248         default:
249                 deb_info("unsupported function for i2c_req %x\n", func);
250                 return -EINVAL;
251         }
252         wValue = (func << 8) | (i2c->port << 4);
253         wIndex = (chipaddr << 8 ) | addr;
254 
255         deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",
256                         func, request_type, req,
257                         wValue & 0xff, wValue >> 8,
258                         wIndex & 0xff, wIndex >> 8);
259 
260         len = usb_control_msg(fc_usb->udev,pipe,
261                         req,
262                         request_type,
263                         wValue,
264                         wIndex,
265                         buf,
266                         buflen,
267                         nWaitTime * HZ);
268         return len == buflen ? 0 : -EREMOTEIO;
269 }
270 
271 /* actual bus specific access functions,
272    make sure prototype are/will be equal to pci */
273 static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc,
274         flexcop_ibi_register reg)
275 {
276         flexcop_ibi_value val;
277         val.raw = 0;
278         flexcop_usb_readwrite_dw(fc, reg, &val.raw, 1);
279         return val;
280 }
281 
282 static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc,
283                 flexcop_ibi_register reg, flexcop_ibi_value val)
284 {
285         return flexcop_usb_readwrite_dw(fc, reg, &val.raw, 0);
286 }
287 
288 static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
289                 flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
290 {
291         if (op == FC_READ)
292                 return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
293                                 USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
294         else
295                 return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
296                                 USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
297 }
298 
299 static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb,
300         u8 *buffer, int buffer_length)
301 {
302         u8 *b;
303         int l;
304 
305         deb_ts("tmp_buffer_length=%d, buffer_length=%d\n",
306                 fc_usb->tmp_buffer_length, buffer_length);
307 
308         if (fc_usb->tmp_buffer_length > 0) {
309                 memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer,
310                                 buffer_length);
311                 fc_usb->tmp_buffer_length += buffer_length;
312                 b = fc_usb->tmp_buffer;
313                 l = fc_usb->tmp_buffer_length;
314         } else {
315                 b=buffer;
316                 l=buffer_length;
317         }
318 
319         while (l >= 190) {
320                 if (*b == 0xff) {
321                         switch (*(b+1) & 0x03) {
322                         case 0x01: /* media packet */
323                                 if (*(b+2) == 0x47)
324                                         flexcop_pass_dmx_packets(
325                                                         fc_usb->fc_dev, b+2, 1);
326                                 else
327                                         deb_ts("not ts packet %*ph\n", 4, b+2);
328                                 b += 190;
329                                 l -= 190;
330                                 break;
331                         default:
332                                 deb_ts("wrong packet type\n");
333                                 l = 0;
334                                 break;
335                         }
336                 } else {
337                         deb_ts("wrong header\n");
338                         l = 0;
339                 }
340         }
341 
342         if (l>0)
343                 memcpy(fc_usb->tmp_buffer, b, l);
344         fc_usb->tmp_buffer_length = l;
345 }
346 
347 static void flexcop_usb_urb_complete(struct urb *urb)
348 {
349         struct flexcop_usb *fc_usb = urb->context;
350         int i;
351 
352         if (urb->actual_length > 0)
353                 deb_ts("urb completed, bufsize: %d actlen; %d\n",
354                         urb->transfer_buffer_length, urb->actual_length);
355 
356         for (i = 0; i < urb->number_of_packets; i++) {
357                 if (urb->iso_frame_desc[i].status < 0) {
358                         err("iso frame descriptor %d has an error: %d\n", i,
359                                 urb->iso_frame_desc[i].status);
360                 } else
361                         if (urb->iso_frame_desc[i].actual_length > 0) {
362                                 deb_ts("passed %d bytes to the demux\n",
363                                         urb->iso_frame_desc[i].actual_length);
364 
365                                 flexcop_usb_process_frame(fc_usb,
366                                         urb->transfer_buffer +
367                                                 urb->iso_frame_desc[i].offset,
368                                         urb->iso_frame_desc[i].actual_length);
369                         }
370                 urb->iso_frame_desc[i].status = 0;
371                 urb->iso_frame_desc[i].actual_length = 0;
372         }
373         usb_submit_urb(urb,GFP_ATOMIC);
374 }
375 
376 static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff)
377 {
378         /* submit/kill iso packets */
379         return 0;
380 }
381 
382 static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
383 {
384         int i;
385         for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
386                 if (fc_usb->iso_urb[i] != NULL) {
387                         deb_ts("unlinking/killing urb no. %d\n",i);
388                         usb_kill_urb(fc_usb->iso_urb[i]);
389                         usb_free_urb(fc_usb->iso_urb[i]);
390                 }
391 
392         if (fc_usb->iso_buffer != NULL)
393                 usb_free_coherent(fc_usb->udev,
394                         fc_usb->buffer_size, fc_usb->iso_buffer,
395                         fc_usb->dma_addr);
396 }
397 
398 static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
399 {
400         u16 frame_size = le16_to_cpu(
401                 fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
402         int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO *
403                 frame_size, i, j, ret;
404         int buffer_offset = 0;
405 
406         deb_ts("creating %d iso-urbs with %d frames "
407                         "each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB,
408                         B2C2_USB_FRAMES_PER_ISO, frame_size, bufsize);
409 
410         fc_usb->iso_buffer = usb_alloc_coherent(fc_usb->udev,
411                         bufsize, GFP_KERNEL, &fc_usb->dma_addr);
412         if (fc_usb->iso_buffer == NULL)
413                 return -ENOMEM;
414 
415         memset(fc_usb->iso_buffer, 0, bufsize);
416         fc_usb->buffer_size = bufsize;
417 
418         /* creating iso urbs */
419         for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
420                 fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,
421                         GFP_ATOMIC);
422                 if (fc_usb->iso_urb[i] == NULL) {
423                         ret = -ENOMEM;
424                         goto urb_error;
425                 }
426         }
427 
428         /* initialising and submitting iso urbs */
429         for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
430                 int frame_offset = 0;
431                 struct urb *urb = fc_usb->iso_urb[i];
432                 deb_ts("initializing and submitting urb no. %d "
433                         "(buf_offset: %d).\n", i, buffer_offset);
434 
435                 urb->dev = fc_usb->udev;
436                 urb->context = fc_usb;
437                 urb->complete = flexcop_usb_urb_complete;
438                 urb->pipe = B2C2_USB_DATA_PIPE;
439                 urb->transfer_flags = URB_ISO_ASAP;
440                 urb->interval = 1;
441                 urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
442                 urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO;
443                 urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset;
444 
445                 buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
446                 for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
447                         deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",
448                                         i, j, frame_offset);
449                         urb->iso_frame_desc[j].offset = frame_offset;
450                         urb->iso_frame_desc[j].length = frame_size;
451                         frame_offset += frame_size;
452                 }
453 
454                 if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) {
455                         err("submitting urb %d failed with %d.", i, ret);
456                         goto urb_error;
457                 }
458                 deb_ts("submitted urb no. %d.\n",i);
459         }
460 
461         /* SRAM */
462         flexcop_sram_set_dest(fc_usb->fc_dev, FC_SRAM_DEST_MEDIA |
463                         FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI,
464                         FC_SRAM_DEST_TARGET_WAN_USB);
465         flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS);
466         flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1);
467         return 0;
468 
469 urb_error:
470         flexcop_usb_transfer_exit(fc_usb);
471         return ret;
472 }
473 
474 static int flexcop_usb_init(struct flexcop_usb *fc_usb)
475 {
476         /* use the alternate setting with the larges buffer */
477         usb_set_interface(fc_usb->udev,0,1);
478         switch (fc_usb->udev->speed) {
479         case USB_SPEED_LOW:
480                 err("cannot handle USB speed because it is too slow.");
481                 return -ENODEV;
482                 break;
483         case USB_SPEED_FULL:
484                 info("running at FULL speed.");
485                 break;
486         case USB_SPEED_HIGH:
487                 info("running at HIGH speed.");
488                 break;
489         case USB_SPEED_UNKNOWN: /* fall through */
490         default:
491                 err("cannot handle USB speed because it is unknown.");
492                 return -ENODEV;
493         }
494         usb_set_intfdata(fc_usb->uintf, fc_usb);
495         return 0;
496 }
497 
498 static void flexcop_usb_exit(struct flexcop_usb *fc_usb)
499 {
500         usb_set_intfdata(fc_usb->uintf, NULL);
501 }
502 
503 static int flexcop_usb_probe(struct usb_interface *intf,
504                 const struct usb_device_id *id)
505 {
506         struct usb_device *udev = interface_to_usbdev(intf);
507         struct flexcop_usb *fc_usb = NULL;
508         struct flexcop_device *fc = NULL;
509         int ret;
510 
511         if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) {
512                 err("out of memory\n");
513                 return -ENOMEM;
514         }
515 
516         /* general flexcop init */
517         fc_usb = fc->bus_specific;
518         fc_usb->fc_dev = fc;
519 
520         fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;
521         fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
522         fc->i2c_request = flexcop_usb_i2c_request;
523         fc->get_mac_addr = flexcop_usb_get_mac_addr;
524 
525         fc->stream_control = flexcop_usb_stream_control;
526 
527         fc->pid_filtering = 1;
528         fc->bus_type = FC_USB;
529 
530         fc->dev = &udev->dev;
531         fc->owner = THIS_MODULE;
532 
533         /* bus specific part */
534         fc_usb->udev = udev;
535         fc_usb->uintf = intf;
536         if ((ret = flexcop_usb_init(fc_usb)) != 0)
537                 goto err_kfree;
538 
539         /* init flexcop */
540         if ((ret = flexcop_device_initialize(fc)) != 0)
541                 goto err_usb_exit;
542 
543         /* xfer init */
544         if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0)
545                 goto err_fc_exit;
546 
547         info("%s successfully initialized and connected.", DRIVER_NAME);
548         return 0;
549 
550 err_fc_exit:
551         flexcop_device_exit(fc);
552 err_usb_exit:
553         flexcop_usb_exit(fc_usb);
554 err_kfree:
555         flexcop_device_kfree(fc);
556         return ret;
557 }
558 
559 static void flexcop_usb_disconnect(struct usb_interface *intf)
560 {
561         struct flexcop_usb *fc_usb = usb_get_intfdata(intf);
562         flexcop_usb_transfer_exit(fc_usb);
563         flexcop_device_exit(fc_usb->fc_dev);
564         flexcop_usb_exit(fc_usb);
565         flexcop_device_kfree(fc_usb->fc_dev);
566         info("%s successfully deinitialized and disconnected.", DRIVER_NAME);
567 }
568 
569 static struct usb_device_id flexcop_usb_table [] = {
570         { USB_DEVICE(0x0af7, 0x0101) },
571         { }
572 };
573 MODULE_DEVICE_TABLE (usb, flexcop_usb_table);
574 
575 /* usb specific object needed to register this driver with the usb subsystem */
576 static struct usb_driver flexcop_usb_driver = {
577         .name           = "b2c2_flexcop_usb",
578         .probe          = flexcop_usb_probe,
579         .disconnect = flexcop_usb_disconnect,
580         .id_table       = flexcop_usb_table,
581 };
582 
583 module_usb_driver(flexcop_usb_driver);
584 
585 MODULE_AUTHOR(DRIVER_AUTHOR);
586 MODULE_DESCRIPTION(DRIVER_NAME);
587 MODULE_LICENSE("GPL");
588 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us