b2c2-usb-core.c 14 KB

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