diff options
Diffstat (limited to 'drivers/media/video/hdpvr/hdpvr-core.c')
-rw-r--r-- | drivers/media/video/hdpvr/hdpvr-core.c | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c new file mode 100644 index 000000000000..e7300b570bb7 --- /dev/null +++ b/drivers/media/video/hdpvr/hdpvr-core.c | |||
@@ -0,0 +1,439 @@ | |||
1 | /* | ||
2 | * Hauppage HD PVR USB driver | ||
3 | * | ||
4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | ||
5 | * Copyright (C) 2008 Janne Grunau (j@jannau.net) | ||
6 | * Copyright (C) 2008 John Poet | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation, version 2. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/uaccess.h> | ||
20 | #include <asm/atomic.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/i2c.h> | ||
24 | |||
25 | #include <linux/videodev2.h> | ||
26 | #include <media/v4l2-dev.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | |||
29 | #include "hdpvr.h" | ||
30 | |||
31 | static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET}; | ||
32 | module_param_array(video_nr, int, NULL, 0); | ||
33 | MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); | ||
34 | |||
35 | /* holds the number of currently registered devices */ | ||
36 | static atomic_t dev_nr = ATOMIC_INIT(-1); | ||
37 | |||
38 | int hdpvr_debug; | ||
39 | module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); | ||
40 | MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); | ||
41 | |||
42 | uint default_video_input = HDPVR_VIDEO_INPUTS; | ||
43 | module_param(default_video_input, uint, S_IRUGO|S_IWUSR); | ||
44 | MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " | ||
45 | "1=S-Video / 2=Composite"); | ||
46 | |||
47 | uint default_audio_input = HDPVR_AUDIO_INPUTS; | ||
48 | module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); | ||
49 | MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " | ||
50 | "1=RCA front / 2=S/PDIF"); | ||
51 | |||
52 | static int boost_audio; | ||
53 | module_param(boost_audio, bool, S_IRUGO|S_IWUSR); | ||
54 | MODULE_PARM_DESC(boost_audio, "boost the audio signal"); | ||
55 | |||
56 | |||
57 | /* table of devices that work with this driver */ | ||
58 | static struct usb_device_id hdpvr_table[] = { | ||
59 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, | ||
60 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, | ||
61 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, | ||
62 | { } /* Terminating entry */ | ||
63 | }; | ||
64 | MODULE_DEVICE_TABLE(usb, hdpvr_table); | ||
65 | |||
66 | |||
67 | void hdpvr_delete(struct hdpvr_device *dev) | ||
68 | { | ||
69 | hdpvr_free_buffers(dev); | ||
70 | |||
71 | if (dev->video_dev) | ||
72 | video_device_release(dev->video_dev); | ||
73 | |||
74 | usb_put_dev(dev->udev); | ||
75 | } | ||
76 | |||
77 | static void challenge(u8 *bytes) | ||
78 | { | ||
79 | u64 *i64P, tmp64; | ||
80 | uint i, idx; | ||
81 | |||
82 | for (idx = 0; idx < 32; ++idx) { | ||
83 | |||
84 | if (idx & 0x3) | ||
85 | bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3]; | ||
86 | |||
87 | switch (idx & 0x3) { | ||
88 | case 0x3: | ||
89 | bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5]; | ||
90 | bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9; | ||
91 | break; | ||
92 | case 0x1: | ||
93 | bytes[0] *= 8; | ||
94 | bytes[0] += 7*idx + 4; | ||
95 | bytes[6] += bytes[3] * 3; | ||
96 | break; | ||
97 | case 0x0: | ||
98 | bytes[3 - (idx >> 3)] = bytes[idx >> 2]; | ||
99 | bytes[5] += bytes[6] * 3; | ||
100 | for (i = 0; i < 3; i++) | ||
101 | bytes[3] *= bytes[3] + 1; | ||
102 | break; | ||
103 | case 0x2: | ||
104 | for (i = 0; i < 3; i++) | ||
105 | bytes[1] *= bytes[6] + 1; | ||
106 | for (i = 0; i < 3; i++) { | ||
107 | i64P = (u64 *)bytes; | ||
108 | tmp64 = le64_to_cpup(i64P); | ||
109 | tmp64 <<= bytes[7] & 0x0f; | ||
110 | *i64P += cpu_to_le64(tmp64); | ||
111 | } | ||
112 | break; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /* try to init the device like the windows driver */ | ||
118 | static int device_authorization(struct hdpvr_device *dev) | ||
119 | { | ||
120 | |||
121 | int ret, retval = -ENOMEM; | ||
122 | char request_type = 0x38, rcv_request = 0x81; | ||
123 | char *response; | ||
124 | #ifdef HDPVR_DEBUG | ||
125 | size_t buf_size = 46; | ||
126 | char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); | ||
127 | if (!print_buf) { | ||
128 | dev_err(&dev->udev->dev, "Out of memory"); | ||
129 | goto error; | ||
130 | } | ||
131 | #endif | ||
132 | |||
133 | mutex_lock(&dev->usbc_mutex); | ||
134 | ret = usb_control_msg(dev->udev, | ||
135 | usb_rcvctrlpipe(dev->udev, 0), | ||
136 | rcv_request, 0x80 | request_type, | ||
137 | 0x0400, 0x0003, | ||
138 | dev->usbc_buf, 46, | ||
139 | 10000); | ||
140 | if (ret != 46) { | ||
141 | dev_err(&dev->udev->dev, | ||
142 | "unexpected answer of status request, len %d", ret); | ||
143 | goto error; | ||
144 | } | ||
145 | #ifdef HDPVR_DEBUG | ||
146 | else { | ||
147 | hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, | ||
148 | sizeof(print_buf), 0); | ||
149 | dev_dbg(&dev->udev->dev, | ||
150 | "Status request returned, len %d: %s\n", | ||
151 | ret, print_buf); | ||
152 | } | ||
153 | #endif | ||
154 | if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION) { | ||
155 | dev->flags &= ~HDPVR_FLAG_AC3_CAP; | ||
156 | } else if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION_AC3) { | ||
157 | dev->flags |= HDPVR_FLAG_AC3_CAP; | ||
158 | } else if (dev->usbc_buf[1] > HDPVR_FIRMWARE_VERSION_AC3) { | ||
159 | dev_notice(&dev->udev->dev, "untested firmware version 0x%x, " | ||
160 | "the driver might not work\n", dev->usbc_buf[1]); | ||
161 | dev->flags |= HDPVR_FLAG_AC3_CAP; | ||
162 | } else { | ||
163 | dev_err(&dev->udev->dev, "unknown firmware version 0x%x\n", | ||
164 | dev->usbc_buf[1]); | ||
165 | ret = -EINVAL; | ||
166 | goto error; | ||
167 | } | ||
168 | |||
169 | response = dev->usbc_buf+38; | ||
170 | #ifdef HDPVR_DEBUG | ||
171 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); | ||
172 | dev_dbg(&dev->udev->dev, "challenge: %s\n", print_buf); | ||
173 | #endif | ||
174 | challenge(response); | ||
175 | #ifdef HDPVR_DEBUG | ||
176 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); | ||
177 | dev_dbg(&dev->udev->dev, " response: %s\n", print_buf); | ||
178 | #endif | ||
179 | |||
180 | msleep(100); | ||
181 | ret = usb_control_msg(dev->udev, | ||
182 | usb_sndctrlpipe(dev->udev, 0), | ||
183 | 0xd1, 0x00 | request_type, | ||
184 | 0x0000, 0x0000, | ||
185 | response, 8, | ||
186 | 10000); | ||
187 | dev_dbg(&dev->udev->dev, "magic request returned %d\n", ret); | ||
188 | mutex_unlock(&dev->usbc_mutex); | ||
189 | |||
190 | retval = ret != 8; | ||
191 | error: | ||
192 | return retval; | ||
193 | } | ||
194 | |||
195 | static int hdpvr_device_init(struct hdpvr_device *dev) | ||
196 | { | ||
197 | int ret; | ||
198 | u8 *buf; | ||
199 | struct hdpvr_video_info *vidinf; | ||
200 | |||
201 | if (device_authorization(dev)) | ||
202 | return -EACCES; | ||
203 | |||
204 | /* default options for init */ | ||
205 | hdpvr_set_options(dev); | ||
206 | |||
207 | /* set filter options */ | ||
208 | mutex_lock(&dev->usbc_mutex); | ||
209 | buf = dev->usbc_buf; | ||
210 | buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00; | ||
211 | ret = usb_control_msg(dev->udev, | ||
212 | usb_sndctrlpipe(dev->udev, 0), | ||
213 | 0x01, 0x38, | ||
214 | CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX, | ||
215 | buf, 4, | ||
216 | 1000); | ||
217 | dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); | ||
218 | mutex_unlock(&dev->usbc_mutex); | ||
219 | |||
220 | vidinf = get_video_info(dev); | ||
221 | if (!vidinf) | ||
222 | dev_dbg(&dev->udev->dev, | ||
223 | "no valid video signal or device init failed\n"); | ||
224 | else | ||
225 | kfree(vidinf); | ||
226 | |||
227 | /* enable fan and bling leds */ | ||
228 | mutex_lock(&dev->usbc_mutex); | ||
229 | buf[0] = 0x1; | ||
230 | ret = usb_control_msg(dev->udev, | ||
231 | usb_sndctrlpipe(dev->udev, 0), | ||
232 | 0xd4, 0x38, 0, 0, buf, 1, | ||
233 | 1000); | ||
234 | dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); | ||
235 | |||
236 | /* boost analog audio */ | ||
237 | buf[0] = boost_audio; | ||
238 | ret = usb_control_msg(dev->udev, | ||
239 | usb_sndctrlpipe(dev->udev, 0), | ||
240 | 0xd5, 0x38, 0, 0, buf, 1, | ||
241 | 1000); | ||
242 | dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); | ||
243 | mutex_unlock(&dev->usbc_mutex); | ||
244 | |||
245 | dev->status = STATUS_IDLE; | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static const struct hdpvr_options hdpvr_default_options = { | ||
250 | .video_std = HDPVR_60HZ, | ||
251 | .video_input = HDPVR_COMPONENT, | ||
252 | .audio_input = HDPVR_RCA_BACK, | ||
253 | .bitrate = 65, /* 6 mbps */ | ||
254 | .peak_bitrate = 90, /* 9 mbps */ | ||
255 | .bitrate_mode = HDPVR_CONSTANT, | ||
256 | .gop_mode = HDPVR_SIMPLE_IDR_GOP, | ||
257 | .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC, | ||
258 | .brightness = 0x86, | ||
259 | .contrast = 0x80, | ||
260 | .hue = 0x80, | ||
261 | .saturation = 0x80, | ||
262 | .sharpness = 0x80, | ||
263 | }; | ||
264 | |||
265 | static int hdpvr_probe(struct usb_interface *interface, | ||
266 | const struct usb_device_id *id) | ||
267 | { | ||
268 | struct hdpvr_device *dev; | ||
269 | struct usb_host_interface *iface_desc; | ||
270 | struct usb_endpoint_descriptor *endpoint; | ||
271 | size_t buffer_size; | ||
272 | int i; | ||
273 | int retval = -ENOMEM; | ||
274 | |||
275 | /* allocate memory for our device state and initialize it */ | ||
276 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
277 | if (!dev) { | ||
278 | err("Out of memory"); | ||
279 | goto error; | ||
280 | } | ||
281 | mutex_init(&dev->io_mutex); | ||
282 | mutex_init(&dev->i2c_mutex); | ||
283 | mutex_init(&dev->usbc_mutex); | ||
284 | dev->usbc_buf = kmalloc(64, GFP_KERNEL); | ||
285 | if (!dev->usbc_buf) { | ||
286 | dev_err(&dev->udev->dev, "Out of memory"); | ||
287 | goto error; | ||
288 | } | ||
289 | |||
290 | init_waitqueue_head(&dev->wait_buffer); | ||
291 | init_waitqueue_head(&dev->wait_data); | ||
292 | |||
293 | dev->workqueue = create_singlethread_workqueue("hdpvr_buffer"); | ||
294 | if (!dev->workqueue) | ||
295 | goto error; | ||
296 | |||
297 | /* init video transfer queues */ | ||
298 | INIT_LIST_HEAD(&dev->free_buff_list); | ||
299 | INIT_LIST_HEAD(&dev->rec_buff_list); | ||
300 | |||
301 | dev->options = hdpvr_default_options; | ||
302 | |||
303 | if (default_video_input < HDPVR_VIDEO_INPUTS) | ||
304 | dev->options.video_input = default_video_input; | ||
305 | |||
306 | if (default_audio_input < HDPVR_AUDIO_INPUTS) | ||
307 | dev->options.audio_input = default_audio_input; | ||
308 | |||
309 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | ||
310 | |||
311 | /* set up the endpoint information */ | ||
312 | /* use only the first bulk-in and bulk-out endpoints */ | ||
313 | iface_desc = interface->cur_altsetting; | ||
314 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
315 | endpoint = &iface_desc->endpoint[i].desc; | ||
316 | |||
317 | if (!dev->bulk_in_endpointAddr && | ||
318 | usb_endpoint_is_bulk_in(endpoint)) { | ||
319 | /* USB interface description is buggy, reported max | ||
320 | * packet size is 512 bytes, windows driver uses 8192 */ | ||
321 | buffer_size = 8192; | ||
322 | dev->bulk_in_size = buffer_size; | ||
323 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
324 | } | ||
325 | |||
326 | } | ||
327 | if (!dev->bulk_in_endpointAddr) { | ||
328 | err("Could not find bulk-in endpoint"); | ||
329 | goto error; | ||
330 | } | ||
331 | |||
332 | /* init the device */ | ||
333 | if (hdpvr_device_init(dev)) { | ||
334 | err("device init failed"); | ||
335 | goto error; | ||
336 | } | ||
337 | |||
338 | mutex_lock(&dev->io_mutex); | ||
339 | if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { | ||
340 | err("allocating transfer buffers failed"); | ||
341 | goto error; | ||
342 | } | ||
343 | mutex_unlock(&dev->io_mutex); | ||
344 | |||
345 | if (hdpvr_register_videodev(dev, | ||
346 | video_nr[atomic_inc_return(&dev_nr)])) { | ||
347 | err("registering videodev failed"); | ||
348 | goto error; | ||
349 | } | ||
350 | |||
351 | |||
352 | /* save our data pointer in this interface device */ | ||
353 | usb_set_intfdata(interface, dev); | ||
354 | |||
355 | /* let the user know what node this device is now attached to */ | ||
356 | v4l2_info(dev->video_dev, "device now attached to /dev/video%d\n", | ||
357 | dev->video_dev->minor); | ||
358 | return 0; | ||
359 | |||
360 | error: | ||
361 | if (dev) { | ||
362 | mutex_unlock(&dev->io_mutex); | ||
363 | /* this frees allocated memory */ | ||
364 | hdpvr_delete(dev); | ||
365 | } | ||
366 | return retval; | ||
367 | } | ||
368 | |||
369 | static void hdpvr_disconnect(struct usb_interface *interface) | ||
370 | { | ||
371 | struct hdpvr_device *dev; | ||
372 | int minor; | ||
373 | |||
374 | dev = usb_get_intfdata(interface); | ||
375 | usb_set_intfdata(interface, NULL); | ||
376 | |||
377 | minor = dev->video_dev->minor; | ||
378 | |||
379 | /* prevent more I/O from starting and stop any ongoing */ | ||
380 | mutex_lock(&dev->io_mutex); | ||
381 | dev->status = STATUS_DISCONNECTED; | ||
382 | video_unregister_device(dev->video_dev); | ||
383 | wake_up_interruptible(&dev->wait_data); | ||
384 | wake_up_interruptible(&dev->wait_buffer); | ||
385 | msleep(100); | ||
386 | flush_workqueue(dev->workqueue); | ||
387 | hdpvr_cancel_queue(dev); | ||
388 | destroy_workqueue(dev->workqueue); | ||
389 | mutex_unlock(&dev->io_mutex); | ||
390 | |||
391 | /* deregister I2C adapter */ | ||
392 | mutex_lock(&dev->i2c_mutex); | ||
393 | if (dev->i2c_adapter) | ||
394 | i2c_del_adapter(dev->i2c_adapter); | ||
395 | kfree(dev->i2c_adapter); | ||
396 | dev->i2c_adapter = NULL; | ||
397 | mutex_unlock(&dev->i2c_mutex); | ||
398 | |||
399 | atomic_dec(&dev_nr); | ||
400 | |||
401 | printk(KERN_INFO "Hauppauge HD PVR: device /dev/video%d disconnected\n", | ||
402 | minor); | ||
403 | |||
404 | kfree(dev->usbc_buf); | ||
405 | kfree(dev); | ||
406 | } | ||
407 | |||
408 | |||
409 | static struct usb_driver hdpvr_usb_driver = { | ||
410 | .name = "hdpvr", | ||
411 | .probe = hdpvr_probe, | ||
412 | .disconnect = hdpvr_disconnect, | ||
413 | .id_table = hdpvr_table, | ||
414 | }; | ||
415 | |||
416 | static int __init hdpvr_init(void) | ||
417 | { | ||
418 | int result; | ||
419 | |||
420 | /* register this driver with the USB subsystem */ | ||
421 | result = usb_register(&hdpvr_usb_driver); | ||
422 | if (result) | ||
423 | err("usb_register failed. Error number %d", result); | ||
424 | |||
425 | return result; | ||
426 | } | ||
427 | |||
428 | static void __exit hdpvr_exit(void) | ||
429 | { | ||
430 | /* deregister this driver with the USB subsystem */ | ||
431 | usb_deregister(&hdpvr_usb_driver); | ||
432 | } | ||
433 | |||
434 | module_init(hdpvr_init); | ||
435 | module_exit(hdpvr_exit); | ||
436 | |||
437 | MODULE_LICENSE("GPL"); | ||
438 | MODULE_AUTHOR("Janne Grunau"); | ||
439 | MODULE_DESCRIPTION("Hauppauge HD PVR driver"); | ||