1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include "usbtv.h"
32
33int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
34{
35 int ret;
36 int pipe = usb_rcvctrlpipe(usbtv->udev, 0);
37 int i;
38
39 for (i = 0; i < size; i++) {
40 u16 index = regs[i][0];
41 u16 value = regs[i][1];
42
43 ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG,
44 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
45 value, index, NULL, 0, 0);
46 if (ret < 0)
47 return ret;
48 }
49
50 return 0;
51}
52
53static int usbtv_probe(struct usb_interface *intf,
54 const struct usb_device_id *id)
55{
56 int ret;
57 int size;
58 struct device *dev = &intf->dev;
59 struct usbtv *usbtv;
60
61
62 if (intf->num_altsetting != 2)
63 return -ENODEV;
64 if (intf->altsetting[1].desc.bNumEndpoints != 4)
65 return -ENODEV;
66
67
68
69 size = usb_endpoint_maxp(&intf->altsetting[1].endpoint[0].desc);
70 size = (size & 0x07ff) * (((size & 0x1800) >> 11) + 1);
71
72
73 usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL);
74 if (usbtv == NULL)
75 return -ENOMEM;
76 usbtv->dev = dev;
77 usbtv->udev = usb_get_dev(interface_to_usbdev(intf));
78
79 usbtv->iso_size = size;
80
81 usb_set_intfdata(intf, usbtv);
82
83 ret = usbtv_video_init(usbtv);
84 if (ret < 0)
85 goto usbtv_video_fail;
86
87 ret = usbtv_audio_init(usbtv);
88 if (ret < 0)
89 goto usbtv_audio_fail;
90
91
92 v4l2_device_get(&usbtv->v4l2_dev);
93
94 dev_info(dev, "Fushicai USBTV007 Audio-Video Grabber\n");
95 return 0;
96
97usbtv_audio_fail:
98 usbtv_video_free(usbtv);
99
100usbtv_video_fail:
101 usb_set_intfdata(intf, NULL);
102 usb_put_dev(usbtv->udev);
103 kfree(usbtv);
104
105 return ret;
106}
107
108static void usbtv_disconnect(struct usb_interface *intf)
109{
110 struct usbtv *usbtv = usb_get_intfdata(intf);
111
112 usb_set_intfdata(intf, NULL);
113
114 if (!usbtv)
115 return;
116
117 usbtv_audio_free(usbtv);
118 usbtv_video_free(usbtv);
119
120 usb_put_dev(usbtv->udev);
121 usbtv->udev = NULL;
122
123
124
125 v4l2_device_put(&usbtv->v4l2_dev);
126}
127
128static struct usb_device_id usbtv_id_table[] = {
129 { USB_DEVICE(0x1b71, 0x3002) },
130 {}
131};
132MODULE_DEVICE_TABLE(usb, usbtv_id_table);
133
134MODULE_AUTHOR("Lubomir Rintel, Federico Simoncelli");
135MODULE_DESCRIPTION("Fushicai USBTV007 Audio-Video Grabber Driver");
136MODULE_LICENSE("Dual BSD/GPL");
137
138static struct usb_driver usbtv_usb_driver = {
139 .name = "usbtv",
140 .id_table = usbtv_id_table,
141 .probe = usbtv_probe,
142 .disconnect = usbtv_disconnect,
143};
144
145module_usb_driver(usbtv_usb_driver);
146