]>
Commit | Line | Data |
---|---|---|
28397ffe GKH |
1 | /* |
2 | * rspiusb.c | |
3 | * | |
4 | * Copyright (C) 2005, 2006 Princeton Instruments | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation version 2 of the License | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 | */ | |
19 | ||
20 | #include <linux/vmalloc.h> | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/errno.h> | |
23 | #include <linux/init.h> | |
24 | #include <linux/slab.h> | |
25 | #include <linux/module.h> | |
26 | #include <linux/smp_lock.h> | |
27 | #include <linux/completion.h> | |
28 | #include <linux/scatterlist.h> | |
29 | #include <linux/usb.h> | |
30 | #include <linux/mm.h> | |
31 | #include <linux/pagemap.h> | |
32 | #include <linux/ioctl.h> | |
33 | #include "rspiusb.h" | |
34 | ||
35 | #ifdef CONFIG_USB_DEBUG | |
36 | static int debug = 1; | |
37 | #else | |
38 | static int debug; | |
39 | #endif | |
40 | /* Use our own dbg macro */ | |
41 | #undef dbg | |
f2d46e24 RG |
42 | #define dbg(format, arg...) \ |
43 | do { \ | |
44 | if (debug) \ | |
45 | printk(KERN_DEBUG __FILE__ ": " format "\n" , ##arg); \ | |
46 | } while (0) | |
28397ffe GKH |
47 | |
48 | /* Version Information */ | |
49 | #define DRIVER_VERSION "V1.0.1" | |
50 | #define DRIVER_AUTHOR "Princeton Instruments" | |
51 | #define DRIVER_DESC "PI USB2.0 Device Driver for Linux" | |
52 | ||
53 | /* Define these values to match your devices */ | |
54 | #define VENDOR_ID 0x0BD7 | |
55 | #define ST133_PID 0xA010 | |
56 | #define PIXIS_PID 0xA026 | |
57 | ||
58 | /* Get a minor range for your devices from the usb maintainer */ | |
59 | #ifdef CONFIG_USB_DYNAMIC_MINORS | |
60 | #define PIUSB_MINOR_BASE 0 | |
61 | #else | |
62 | #define PIUSB_MINOR_BASE 192 | |
63 | #endif | |
64 | ||
65 | /* prevent races between open() and disconnect() */ | |
66 | static DECLARE_MUTEX(disconnect_sem); | |
67 | ||
68 | /* Structure to hold all of our device specific stuff */ | |
69 | struct device_extension { | |
f2d46e24 RG |
70 | struct usb_device *udev; /* save off the usb device pointer */ |
71 | struct usb_interface *interface; /* the interface for this device */ | |
72 | unsigned char minor; /* the starting minor number | |
73 | * for this device | |
74 | */ | |
28397ffe GKH |
75 | size_t bulk_in_size_returned; |
76 | int bulk_in_byte_trk; | |
77 | struct urb ***PixelUrb; | |
78 | int frameIdx; | |
79 | int urbIdx; | |
80 | unsigned int *maplist_numPagesMapped; | |
f2d46e24 RG |
81 | int open; /* if the port is open or not */ |
82 | int present; /* if the device is not disconnected */ | |
83 | int userBufMapped; /* has the user buffer been mapped ? */ | |
84 | struct scatterlist **sgl; /* scatter-gather list for user buffer */ | |
28397ffe GKH |
85 | unsigned int *sgEntries; |
86 | struct kref kref; | |
87 | int gotPixelData; | |
88 | int pendingWrite; | |
89 | char **pendedPixelUrbs; | |
f2d46e24 RG |
90 | int iama; /* PIXIS or ST133 */ |
91 | int num_frames; /* the number of frames that will fit | |
92 | * in the user buffer | |
93 | */ | |
28397ffe GKH |
94 | int active_frame; |
95 | unsigned long frameSize; | |
96 | struct semaphore sem; | |
f2d46e24 | 97 | unsigned int hEP[8]; /* FX2 specific endpoints */ |
28397ffe | 98 | }; |
28397ffe | 99 | |
f2d46e24 RG |
100 | #define to_pi_dev(d) container_of(d, struct device_extension, kref) |
101 | ||
102 | /* Prototypes */ | |
28397ffe GKH |
103 | static int MapUserBuffer(struct ioctl_struct *, struct device_extension *); |
104 | static int UnMapUserBuffer(struct device_extension *); | |
105 | static int piusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |
106 | unsigned long arg); | |
f2d46e24 RG |
107 | static int piusb_output(struct ioctl_struct *, unsigned char *, int, |
108 | struct device_extension *); | |
28397ffe GKH |
109 | static struct usb_driver piusb_driver; |
110 | ||
111 | /* table of devices that work with this driver */ | |
112 | static struct usb_device_id pi_device_table[] = { | |
113 | {USB_DEVICE(VENDOR_ID, ST133_PID)}, | |
114 | {USB_DEVICE(VENDOR_ID, PIXIS_PID)}, | |
f2d46e24 | 115 | {0, } /* Terminating entry */ |
28397ffe GKH |
116 | }; |
117 | ||
118 | MODULE_DEVICE_TABLE(usb, pi_device_table); | |
119 | ||
f2d46e24 RG |
120 | static int lastErr; |
121 | static int errCnt; | |
28397ffe GKH |
122 | |
123 | static void piusb_delete(struct kref *kref) | |
124 | { | |
125 | struct device_extension *pdx = to_pi_dev(kref); | |
126 | ||
127 | dev_dbg(&pdx->udev->dev, "%s\n", __func__); | |
128 | usb_put_dev(pdx->udev); | |
129 | kfree(pdx); | |
130 | } | |
131 | ||
132 | static int piusb_open(struct inode *inode, struct file *file) | |
133 | { | |
134 | struct device_extension *pdx = NULL; | |
135 | struct usb_interface *interface; | |
136 | int subminor; | |
137 | int retval = 0; | |
138 | ||
139 | dbg("Piusb_Open()"); | |
140 | subminor = iminor(inode); | |
141 | interface = usb_find_interface(&piusb_driver, subminor); | |
142 | if (!interface) { | |
143 | printk(KERN_ERR "%s - error, can't find device for minor %d\n", | |
144 | __func__, subminor); | |
145 | retval = -ENODEV; | |
146 | goto exit_no_device; | |
147 | } | |
148 | ||
149 | pdx = usb_get_intfdata(interface); | |
150 | if (!pdx) { | |
151 | retval = -ENODEV; | |
152 | goto exit_no_device; | |
153 | } | |
154 | dbg("Alternate Setting = %d", interface->num_altsetting); | |
155 | ||
f2d46e24 RG |
156 | pdx->bulk_in_size_returned = 0; |
157 | pdx->bulk_in_byte_trk = 0; | |
158 | pdx->PixelUrb = NULL; | |
159 | pdx->frameIdx = 0; | |
160 | pdx->urbIdx = 0; | |
161 | pdx->maplist_numPagesMapped = NULL; | |
162 | pdx->userBufMapped = 0; | |
163 | pdx->sgl = NULL; | |
164 | pdx->sgEntries = NULL; | |
28397ffe GKH |
165 | pdx->gotPixelData = 0; |
166 | pdx->pendingWrite = 0; | |
f2d46e24 | 167 | pdx->pendedPixelUrbs = NULL; |
28397ffe GKH |
168 | pdx->num_frames = 0; |
169 | pdx->active_frame = 0; | |
f2d46e24 RG |
170 | pdx->frameSize = 0; |
171 | ||
28397ffe GKH |
172 | /* increment our usage count for the device */ |
173 | kref_get(&pdx->kref); | |
f2d46e24 | 174 | |
28397ffe GKH |
175 | /* save our object in the file's private structure */ |
176 | file->private_data = pdx; | |
f2d46e24 RG |
177 | |
178 | exit_no_device: | |
28397ffe GKH |
179 | return retval; |
180 | } | |
181 | ||
182 | static int piusb_release(struct inode *inode, struct file *file) | |
183 | { | |
184 | struct device_extension *pdx; | |
185 | int retval = 0; | |
186 | ||
187 | dbg("Piusb_Release()"); | |
188 | pdx = (struct device_extension *)file->private_data; | |
189 | if (pdx == NULL) { | |
190 | dbg("%s - object is NULL", __func__); | |
f2d46e24 RG |
191 | retval = -ENODEV; |
192 | goto object_null; | |
28397ffe GKH |
193 | } |
194 | /* decrement the count on our device */ | |
195 | kref_put(&pdx->kref, piusb_delete); | |
f2d46e24 RG |
196 | |
197 | object_null: | |
28397ffe GKH |
198 | return retval; |
199 | } | |
200 | ||
c854b5e5 RG |
201 | static int pixis_io(struct ioctl_struct *ctrl, struct device_extension *pdx, |
202 | struct ioctl_struct *arg) | |
203 | { | |
204 | unsigned int numToRead = 0; | |
205 | unsigned int totalRead = 0; | |
206 | unsigned char *uBuf; | |
207 | int numbytes; | |
208 | int i; | |
209 | ||
210 | uBuf = kmalloc(ctrl->numbytes, GFP_KERNEL); | |
211 | if (!uBuf) { | |
212 | dbg("Alloc for uBuf failed"); | |
213 | return 0; | |
214 | } | |
215 | numbytes = (int) ctrl->numbytes; | |
216 | numToRead = (unsigned int) ctrl->numbytes; | |
217 | dbg("numbytes to read = %d", numbytes); | |
218 | dbg("endpoint # %d", ctrl->endpoint); | |
219 | ||
220 | if (copy_from_user(uBuf, ctrl->pData, numbytes)) | |
221 | dbg("copying ctrl->pData to dummyBuf failed"); | |
222 | ||
223 | do { | |
224 | i = usb_bulk_msg(pdx->udev, pdx->hEP[ctrl->endpoint], | |
225 | (uBuf + totalRead), | |
226 | /* EP0 can only handle 64 bytes at a time */ | |
227 | (numToRead > 64) ? 64 : numToRead, | |
228 | &numbytes, HZ * 10); | |
229 | if (i) { | |
230 | dbg("CMD = %s, Address = 0x%02X", | |
231 | ((uBuf[3] == 0x02) ? "WRITE" : "READ"), | |
232 | uBuf[1]); | |
233 | dbg("Number of bytes Attempted to read = %d", | |
234 | (int)ctrl->numbytes); | |
235 | dbg("Blocking ReadI/O Failed with status %d", i); | |
236 | kfree(uBuf); | |
237 | return -1; | |
238 | } | |
239 | dbg("Pixis EP0 Read %d bytes", numbytes); | |
240 | totalRead += numbytes; | |
241 | numToRead -= numbytes; | |
242 | } while (numToRead); | |
243 | ||
244 | memcpy(ctrl->pData, uBuf, totalRead); | |
245 | dbg("Total Bytes Read from PIXIS EP0 = %d", totalRead); | |
246 | ctrl->numbytes = totalRead; | |
247 | ||
248 | if (copy_to_user(arg, ctrl, sizeof(struct ioctl_struct))) | |
249 | dbg("copy_to_user failed in IORB"); | |
250 | ||
251 | kfree(uBuf); | |
252 | return ctrl->numbytes; | |
253 | } | |
254 | ||
c854b5e5 RG |
255 | static int pixel_data(struct ioctl_struct *ctrl, struct device_extension *pdx) |
256 | { | |
257 | int i; | |
258 | ||
259 | if (!pdx->gotPixelData) | |
260 | return 0; | |
261 | ||
262 | pdx->gotPixelData = 0; | |
263 | ctrl->numbytes = pdx->bulk_in_size_returned; | |
264 | pdx->bulk_in_size_returned -= pdx->frameSize; | |
265 | ||
266 | for (i = 0; i < pdx->maplist_numPagesMapped[pdx->active_frame]; i++) | |
267 | SetPageDirty(pdx->sgl[pdx->active_frame][i].page_link); | |
268 | ||
269 | pdx->active_frame = ((pdx->active_frame + 1) % pdx->num_frames); | |
270 | ||
271 | return ctrl->numbytes; | |
272 | } | |
273 | ||
28397ffe GKH |
274 | /** |
275 | * piusb_ioctl | |
276 | */ | |
277 | static int piusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |
278 | unsigned long arg) | |
279 | { | |
280 | struct device_extension *pdx; | |
281 | char dummyCtlBuf[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
282 | unsigned long devRB = 0; | |
28397ffe GKH |
283 | int err = 0; |
284 | int retval = 0; | |
285 | struct ioctl_struct ctrl; | |
28397ffe GKH |
286 | unsigned short controlData = 0; |
287 | ||
288 | pdx = (struct device_extension *)file->private_data; | |
289 | /* verify that the device wasn't unplugged */ | |
290 | if (!pdx->present) { | |
291 | dbg("No Device Present\n"); | |
292 | return -ENODEV; | |
293 | } | |
294 | /* fill in your device specific stuff here */ | |
295 | if (_IOC_DIR(cmd) & _IOC_READ) | |
f2d46e24 RG |
296 | err = !access_ok(VERIFY_WRITE, (void __user *)arg, |
297 | _IOC_SIZE(cmd)); | |
28397ffe | 298 | else if (_IOC_DIR(cmd) & _IOC_WRITE) |
f2d46e24 RG |
299 | err = !access_ok(VERIFY_READ, (void __user *)arg, |
300 | _IOC_SIZE(cmd)); | |
28397ffe GKH |
301 | if (err) { |
302 | dev_err(&pdx->udev->dev, "return with error = %d\n", err); | |
303 | return -EFAULT; | |
304 | } | |
305 | switch (cmd) { | |
306 | case PIUSB_GETVNDCMD: | |
307 | if (copy_from_user | |
308 | (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) | |
6546f08d | 309 | dev_err(&pdx->udev->dev, "copy_from_user failed\n"); |
28397ffe GKH |
310 | dbg("%s %x\n", "Get Vendor Command = ", ctrl.cmd); |
311 | retval = | |
312 | usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0), | |
313 | ctrl.cmd, USB_DIR_IN, 0, 0, &devRB, | |
314 | ctrl.numbytes, HZ * 10); | |
315 | if (ctrl.cmd == 0xF1) { | |
316 | dbg("FW Version returned from HW = %ld.%ld", | |
317 | (devRB >> 8), (devRB & 0xFF)); | |
318 | } | |
f2d46e24 RG |
319 | if (retval >= 0) |
320 | retval = (int)devRB; | |
321 | return retval; | |
322 | ||
28397ffe GKH |
323 | case PIUSB_SETVNDCMD: |
324 | if (copy_from_user | |
325 | (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) | |
6546f08d | 326 | dev_err(&pdx->udev->dev, "copy_from_user failed\n"); |
f2d46e24 | 327 | /* dbg( "%s %x", "Set Vendor Command = ",ctrl.cmd ); */ |
28397ffe GKH |
328 | controlData = ctrl.pData[0]; |
329 | controlData |= (ctrl.pData[1] << 8); | |
f2d46e24 RG |
330 | /* dbg( "%s %d", "Vendor Data =",controlData ); */ |
331 | retval = usb_control_msg(pdx->udev, | |
332 | usb_sndctrlpipe(pdx->udev, 0), | |
333 | ctrl.cmd, | |
334 | (USB_DIR_OUT | USB_TYPE_VENDOR | |
335 | /* | USB_RECIP_ENDPOINT */), | |
336 | controlData, 0, | |
337 | &dummyCtlBuf, ctrl.numbytes, HZ * 10); | |
28397ffe | 338 | return retval; |
f2d46e24 | 339 | |
28397ffe GKH |
340 | case PIUSB_ISHIGHSPEED: |
341 | return ((pdx->udev->speed == USB_SPEED_HIGH) ? 1 : 0); | |
f2d46e24 | 342 | |
28397ffe GKH |
343 | case PIUSB_WRITEPIPE: |
344 | if (copy_from_user(&ctrl, (void __user *)arg, _IOC_SIZE(cmd))) | |
f2d46e24 RG |
345 | dev_err(&pdx->udev->dev, |
346 | "copy_from_user WRITE_DUMMY failed\n"); | |
28397ffe GKH |
347 | if (!access_ok(VERIFY_READ, ctrl.pData, ctrl.numbytes)) { |
348 | dbg("can't access pData"); | |
349 | return 0; | |
350 | } | |
f2d46e24 | 351 | piusb_output(&ctrl, ctrl.pData /* uBuf */, ctrl.numbytes, pdx); |
28397ffe | 352 | return ctrl.numbytes; |
f2d46e24 | 353 | |
28397ffe GKH |
354 | case PIUSB_USERBUFFER: |
355 | if (copy_from_user | |
356 | (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) | |
6546f08d | 357 | dev_err(&pdx->udev->dev, "copy_from_user failed\n"); |
f2d46e24 RG |
358 | return MapUserBuffer((struct ioctl_struct *) &ctrl, pdx); |
359 | ||
28397ffe | 360 | case PIUSB_UNMAP_USERBUFFER: |
f2d46e24 RG |
361 | retval = UnMapUserBuffer(pdx); |
362 | return retval; | |
363 | ||
28397ffe | 364 | case PIUSB_READPIPE: |
c854b5e5 RG |
365 | if (copy_from_user(&ctrl, (void __user *)arg, |
366 | sizeof(struct ioctl_struct))) | |
6546f08d | 367 | dev_err(&pdx->udev->dev, "copy_from_user failed\n"); |
c854b5e5 | 368 | |
14e8bcd0 RG |
369 | if (((0 == ctrl.endpoint) && (PIXIS_PID == pdx->iama)) || |
370 | (1 == ctrl.endpoint) || /* ST133IO */ | |
371 | (4 == ctrl.endpoint)) /* PIXIS IO */ | |
372 | return pixis_io(&ctrl, pdx, | |
373 | (struct ioctl_struct *)arg); | |
374 | else if ((0 == ctrl.endpoint) || /* ST133 Pixel Data */ | |
375 | (2 == ctrl.endpoint) || /* PIXIS Ping */ | |
376 | (3 == ctrl.endpoint)) /* PIXIS Pong */ | |
c854b5e5 | 377 | return pixel_data(&ctrl, pdx); |
f2d46e24 | 378 | |
28397ffe | 379 | break; |
f2d46e24 | 380 | |
28397ffe GKH |
381 | case PIUSB_WHATCAMERA: |
382 | return pdx->iama; | |
f2d46e24 | 383 | |
28397ffe GKH |
384 | case PIUSB_SETFRAMESIZE: |
385 | dbg("PIUSB_SETFRAMESIZE"); | |
386 | if (copy_from_user | |
387 | (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) | |
6546f08d | 388 | dev_err(&pdx->udev->dev, "copy_from_user failed\n"); |
28397ffe GKH |
389 | pdx->frameSize = ctrl.numbytes; |
390 | pdx->num_frames = ctrl.numFrames; | |
391 | if (!pdx->sgl) | |
392 | pdx->sgl = | |
393 | kmalloc(sizeof(struct scatterlist *) * | |
394 | pdx->num_frames, GFP_KERNEL); | |
395 | if (!pdx->sgEntries) | |
396 | pdx->sgEntries = | |
397 | kmalloc(sizeof(unsigned int) * pdx->num_frames, | |
398 | GFP_KERNEL); | |
399 | if (!pdx->PixelUrb) | |
400 | pdx->PixelUrb = | |
401 | kmalloc(sizeof(struct urb **) * pdx->num_frames, | |
402 | GFP_KERNEL); | |
403 | if (!pdx->maplist_numPagesMapped) | |
404 | pdx->maplist_numPagesMapped = | |
405 | vmalloc(sizeof(unsigned int) * pdx->num_frames); | |
406 | if (!pdx->pendedPixelUrbs) | |
407 | pdx->pendedPixelUrbs = | |
408 | kmalloc(sizeof(char *) * pdx->num_frames, | |
409 | GFP_KERNEL); | |
410 | return 0; | |
f2d46e24 | 411 | |
28397ffe GKH |
412 | default: |
413 | dbg("%s\n", "No IOCTL found"); | |
414 | break; | |
415 | ||
416 | } | |
417 | /* return that we did not understand this ioctl call */ | |
418 | dbg("Returning -ENOTTY"); | |
419 | return -ENOTTY; | |
420 | } | |
421 | ||
422 | static void piusb_write_bulk_callback(struct urb *urb) | |
423 | { | |
424 | struct device_extension *pdx = urb->context; | |
425 | int status = urb->status; | |
426 | ||
427 | /* sync/async unlink faults aren't errors */ | |
428 | if (status && !(status == -ENOENT || status == -ECONNRESET)) | |
429 | dev_dbg(&urb->dev->dev, | |
430 | "%s - nonzero write bulk status received: %d", | |
431 | __func__, status); | |
432 | ||
433 | pdx->pendingWrite = 0; | |
434 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | |
435 | urb->transfer_buffer, urb->transfer_dma); | |
436 | } | |
437 | ||
f2d46e24 | 438 | int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len, |
28397ffe GKH |
439 | struct device_extension *pdx) |
440 | { | |
441 | struct urb *urb = NULL; | |
442 | int err = 0; | |
443 | unsigned char *kbuf = NULL; | |
444 | ||
445 | urb = usb_alloc_urb(0, GFP_KERNEL); | |
446 | if (urb != NULL) { | |
447 | kbuf = | |
448 | usb_buffer_alloc(pdx->udev, len, GFP_KERNEL, | |
449 | &urb->transfer_dma); | |
450 | if (!kbuf) { | |
6546f08d | 451 | dev_err(&pdx->udev->dev, "buffer_alloc failed\n"); |
28397ffe GKH |
452 | return -ENOMEM; |
453 | } | |
454 | memcpy(kbuf, uBuf, len); | |
455 | usb_fill_bulk_urb(urb, pdx->udev, pdx->hEP[io->endpoint], kbuf, | |
456 | len, piusb_write_bulk_callback, pdx); | |
457 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
458 | err = usb_submit_urb(urb, GFP_KERNEL); | |
459 | if (err) { | |
460 | dev_err(&pdx->udev->dev, | |
461 | "WRITE ERROR:submit urb error = %d\n", err); | |
462 | } | |
463 | pdx->pendingWrite = 1; | |
464 | usb_free_urb(urb); | |
465 | } | |
466 | return -EINPROGRESS; | |
467 | } | |
468 | ||
469 | static int UnMapUserBuffer(struct device_extension *pdx) | |
470 | { | |
471 | int i = 0; | |
472 | int k = 0; | |
473 | unsigned int epAddr; | |
f2d46e24 | 474 | |
28397ffe GKH |
475 | for (k = 0; k < pdx->num_frames; k++) { |
476 | dbg("Killing Urbs for Frame %d", k); | |
477 | for (i = 0; i < pdx->sgEntries[k]; i++) { | |
478 | usb_kill_urb(pdx->PixelUrb[k][i]); | |
479 | usb_free_urb(pdx->PixelUrb[k][i]); | |
480 | pdx->pendedPixelUrbs[k][i] = 0; | |
481 | } | |
482 | dbg("Urb error count = %d", errCnt); | |
483 | errCnt = 0; | |
484 | dbg("Urbs free'd and Killed for Frame %d", k); | |
485 | } | |
486 | ||
487 | for (k = 0; k < pdx->num_frames; k++) { | |
f2d46e24 RG |
488 | if (pdx->iama == PIXIS_PID) |
489 | /* which EP should we map this frame to ? */ | |
490 | /* PONG, odd frames: hEP[3] */ | |
491 | /* PING, even frames and zero hEP[2] */ | |
492 | epAddr = (k % 2) ? pdx->hEP[3] : pdx->hEP[2]; | |
493 | else | |
494 | /* ST133 only has 1 endpoint for Pixel data transfer */ | |
28397ffe | 495 | epAddr = pdx->hEP[0]; |
f2d46e24 | 496 | |
28397ffe GKH |
497 | usb_buffer_unmap_sg(pdx->udev, epAddr, pdx->sgl[k], |
498 | pdx->maplist_numPagesMapped[k]); | |
f2d46e24 | 499 | for (i = 0; i < pdx->maplist_numPagesMapped[k]; i++) |
28397ffe | 500 | page_cache_release(pdx->sgl[k][i].page_link); |
28397ffe GKH |
501 | kfree(pdx->sgl[k]); |
502 | kfree(pdx->PixelUrb[k]); | |
503 | kfree(pdx->pendedPixelUrbs[k]); | |
504 | pdx->sgl[k] = NULL; | |
505 | pdx->PixelUrb[k] = NULL; | |
506 | pdx->pendedPixelUrbs[k] = NULL; | |
507 | } | |
f2d46e24 | 508 | |
28397ffe GKH |
509 | kfree(pdx->sgEntries); |
510 | vfree(pdx->maplist_numPagesMapped); | |
511 | pdx->sgEntries = NULL; | |
512 | pdx->maplist_numPagesMapped = NULL; | |
513 | kfree(pdx->sgl); | |
514 | kfree(pdx->pendedPixelUrbs); | |
515 | kfree(pdx->PixelUrb); | |
516 | pdx->sgl = NULL; | |
517 | pdx->pendedPixelUrbs = NULL; | |
518 | pdx->PixelUrb = NULL; | |
f2d46e24 | 519 | |
28397ffe GKH |
520 | return 0; |
521 | } | |
522 | ||
523 | static void piusb_readPIXEL_callback(struct urb *urb) | |
524 | { | |
525 | int i = 0; | |
526 | struct device_extension *pdx = urb->context; | |
527 | int status = urb->status; | |
528 | ||
529 | if (status && !(status == -ENOENT || status == -ECONNRESET)) { | |
530 | dbg("%s - nonzero read bulk status received: %d", __func__, | |
531 | status); | |
532 | dbg("Error in read EP2 callback"); | |
533 | dbg("FrameIndex = %d", pdx->frameIdx); | |
534 | dbg("Bytes received before problem occurred = %d", | |
535 | pdx->bulk_in_byte_trk); | |
536 | dbg("Urb Idx = %d", pdx->urbIdx); | |
537 | pdx->pendedPixelUrbs[pdx->frameIdx][pdx->urbIdx] = 0; | |
538 | } else { | |
539 | pdx->bulk_in_byte_trk += urb->actual_length; | |
f2d46e24 RG |
540 | i = usb_submit_urb(urb, GFP_ATOMIC); /* resubmit the URB */ |
541 | if (i) { | |
542 | errCnt++; | |
543 | if (i != lastErr) { | |
544 | dbg("submit urb in callback failed " | |
545 | "with error code %d", i); | |
546 | lastErr = i; | |
547 | } | |
548 | } else { | |
549 | pdx->urbIdx++; /* point to next URB when we callback */ | |
550 | if (pdx->bulk_in_byte_trk >= pdx->frameSize) { | |
551 | pdx->bulk_in_size_returned = | |
552 | pdx->bulk_in_byte_trk; | |
553 | pdx->bulk_in_byte_trk = 0; | |
554 | pdx->gotPixelData = 1; | |
555 | pdx->frameIdx = | |
556 | ((pdx->frameIdx + | |
557 | 1) % pdx->num_frames); | |
558 | pdx->urbIdx = 0; | |
28397ffe GKH |
559 | } |
560 | } | |
561 | } | |
562 | } | |
563 | ||
564 | /* MapUserBuffer( | |
565 | inputs: | |
f2d46e24 RG |
566 | struct ioctl_struct *io - structure containing user address, |
567 | frame #, and size | |
28397ffe | 568 | struct device_extension *pdx - the PIUSB device extension |
f2d46e24 | 569 | |
28397ffe GKH |
570 | returns: |
571 | int - status of the task | |
f2d46e24 | 572 | |
28397ffe | 573 | Notes: |
f2d46e24 RG |
574 | MapUserBuffer maps a buffer passed down through an ioctl. |
575 | The user buffer is Page Aligned by the app and then passed down. | |
576 | The function get_free_pages(...) does the actual mapping of the buffer | |
577 | from user space to kernel space. | |
578 | From there a scatterlist is created from all the pages. | |
579 | The next function called is to usb_buffer_map_sg which allocated | |
580 | DMA addresses for each page, even coalescing them if possible. | |
581 | The DMA address is placed in the scatterlist structure. | |
582 | The function returns the number of DMA addresses. | |
583 | This may or may not be equal to the number of pages that | |
584 | the user buffer uses. | |
585 | We then build an URB for each DMA address and then submit them. | |
586 | */ | |
587 | ||
588 | /* | |
589 | int MapUserBuffer(unsigned long uaddr, unsigned long numbytes, | |
590 | unsigned long frameInfo, struct device_extension *pdx) | |
28397ffe | 591 | */ |
28397ffe GKH |
592 | static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx) |
593 | { | |
594 | unsigned long uaddr; | |
595 | unsigned long numbytes; | |
f2d46e24 | 596 | int frameInfo; /* which frame we're mapping */ |
28397ffe GKH |
597 | unsigned int epAddr = 0; |
598 | unsigned long count = 0; | |
599 | int i = 0; | |
600 | int k = 0; | |
601 | int err = 0; | |
602 | struct page **maplist_p; | |
603 | int numPagesRequired; | |
f2d46e24 | 604 | |
28397ffe GKH |
605 | frameInfo = io->numFrames; |
606 | uaddr = (unsigned long)io->pData; | |
607 | numbytes = io->numbytes; | |
608 | ||
f2d46e24 RG |
609 | if (pdx->iama == PIXIS_PID) { |
610 | /* which EP should we map this frame to ? */ | |
611 | /* PONG, odd frames: hEP[3] */ | |
612 | /* PING, even frames and zero hEP[2] */ | |
613 | epAddr = (frameInfo % 2) ? pdx->hEP[3] : pdx->hEP[2]; | |
28397ffe GKH |
614 | dbg("Pixis Frame #%d: EP=%d", frameInfo, |
615 | (epAddr == pdx->hEP[2]) ? 2 : 4); | |
f2d46e24 | 616 | } else { /* ST133 only has 1 endpoint for Pixel data transfer */ |
28397ffe GKH |
617 | epAddr = pdx->hEP[0]; |
618 | dbg("ST133 Frame #%d: EP=2", frameInfo); | |
619 | } | |
620 | count = numbytes; | |
621 | dbg("UserAddress = 0x%08lX", uaddr); | |
622 | dbg("numbytes = %d", (int)numbytes); | |
f2d46e24 RG |
623 | |
624 | /* number of pages to map the entire user space DMA buffer */ | |
28397ffe GKH |
625 | numPagesRequired = |
626 | ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; | |
627 | dbg("Number of pages needed = %d", numPagesRequired); | |
f2d46e24 | 628 | maplist_p = vmalloc(numPagesRequired * sizeof(struct page)); |
28397ffe GKH |
629 | if (!maplist_p) { |
630 | dbg("Can't Allocate Memory for maplist_p"); | |
631 | return -ENOMEM; | |
632 | } | |
f2d46e24 RG |
633 | |
634 | /* map the user buffer to kernel memory */ | |
28397ffe | 635 | down_write(¤t->mm->mmap_sem); |
f2d46e24 RG |
636 | pdx->maplist_numPagesMapped[frameInfo] = get_user_pages(current, |
637 | current->mm, (uaddr & PAGE_MASK), numPagesRequired, | |
638 | WRITE, 0 /* Don't Force*/, maplist_p, NULL); | |
28397ffe GKH |
639 | up_write(¤t->mm->mmap_sem); |
640 | dbg("Number of pages mapped = %d", | |
641 | pdx->maplist_numPagesMapped[frameInfo]); | |
f2d46e24 | 642 | |
28397ffe GKH |
643 | for (i = 0; i < pdx->maplist_numPagesMapped[frameInfo]; i++) |
644 | flush_dcache_page(maplist_p[i]); | |
645 | if (!pdx->maplist_numPagesMapped[frameInfo]) { | |
646 | dbg("get_user_pages() failed"); | |
647 | vfree(maplist_p); | |
648 | return -ENOMEM; | |
649 | } | |
f2d46e24 RG |
650 | |
651 | /* need to create a scatterlist that spans each frame | |
652 | * that can fit into the mapped buffer | |
653 | */ | |
28397ffe GKH |
654 | pdx->sgl[frameInfo] = |
655 | kmalloc((pdx->maplist_numPagesMapped[frameInfo] * | |
656 | sizeof(struct scatterlist)), GFP_ATOMIC); | |
657 | if (!pdx->sgl[frameInfo]) { | |
658 | vfree(maplist_p); | |
659 | dbg("can't allocate mem for sgl"); | |
660 | return -ENOMEM; | |
661 | } | |
662 | pdx->sgl[frameInfo][0].page_link = maplist_p[0]; | |
663 | pdx->sgl[frameInfo][0].offset = uaddr & ~PAGE_MASK; | |
664 | if (pdx->maplist_numPagesMapped[frameInfo] > 1) { | |
665 | pdx->sgl[frameInfo][0].length = | |
666 | PAGE_SIZE - pdx->sgl[frameInfo][0].offset; | |
667 | count -= pdx->sgl[frameInfo][0].length; | |
668 | for (k = 1; k < pdx->maplist_numPagesMapped[frameInfo]; k++) { | |
669 | pdx->sgl[frameInfo][k].offset = 0; | |
670 | pdx->sgl[frameInfo][k].page_link = maplist_p[k]; | |
671 | pdx->sgl[frameInfo][k].length = | |
672 | (count < PAGE_SIZE) ? count : PAGE_SIZE; | |
f2d46e24 | 673 | count -= PAGE_SIZE; /* example had PAGE_SIZE here */ |
28397ffe GKH |
674 | } |
675 | } else { | |
676 | pdx->sgl[frameInfo][0].length = count; | |
677 | } | |
678 | pdx->sgEntries[frameInfo] = | |
679 | usb_buffer_map_sg(pdx->udev, epAddr, pdx->sgl[frameInfo], | |
680 | pdx->maplist_numPagesMapped[frameInfo]); | |
681 | dbg("number of sgEntries = %d", pdx->sgEntries[frameInfo]); | |
682 | pdx->userBufMapped = 1; | |
683 | vfree(maplist_p); | |
f2d46e24 RG |
684 | |
685 | /* Create and Send the URB's for each s/g entry */ | |
28397ffe GKH |
686 | pdx->PixelUrb[frameInfo] = |
687 | kmalloc(pdx->sgEntries[frameInfo] * sizeof(struct urb *), | |
688 | GFP_KERNEL); | |
689 | if (!pdx->PixelUrb[frameInfo]) { | |
690 | dbg("Can't Allocate Memory for Urb"); | |
691 | return -ENOMEM; | |
692 | } | |
693 | for (i = 0; i < pdx->sgEntries[frameInfo]; i++) { | |
f2d46e24 RG |
694 | /* 0 iso packets because we're using BULK transfers */ |
695 | pdx->PixelUrb[frameInfo][i] = usb_alloc_urb(0, GFP_KERNEL); | |
28397ffe GKH |
696 | usb_fill_bulk_urb(pdx->PixelUrb[frameInfo][i], |
697 | pdx->udev, | |
698 | epAddr, | |
699 | (dma_addr_t *) sg_dma_address(&pdx-> | |
700 | sgl[frameInfo] | |
701 | [i]), | |
702 | sg_dma_len(&pdx->sgl[frameInfo][i]), | |
703 | piusb_readPIXEL_callback, (void *)pdx); | |
704 | pdx->PixelUrb[frameInfo][i]->transfer_dma = | |
705 | sg_dma_address(&pdx->sgl[frameInfo][i]); | |
706 | pdx->PixelUrb[frameInfo][i]->transfer_flags = | |
707 | URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT; | |
708 | } | |
f2d46e24 RG |
709 | /* only interrupt when last URB completes */ |
710 | pdx->PixelUrb[frameInfo][--i]->transfer_flags &= ~URB_NO_INTERRUPT; | |
28397ffe GKH |
711 | pdx->pendedPixelUrbs[frameInfo] = |
712 | kmalloc((pdx->sgEntries[frameInfo] * sizeof(char)), GFP_KERNEL); | |
713 | if (!pdx->pendedPixelUrbs[frameInfo]) | |
714 | dbg("Can't allocate Memory for pendedPixelUrbs"); | |
715 | for (i = 0; i < pdx->sgEntries[frameInfo]; i++) { | |
716 | err = usb_submit_urb(pdx->PixelUrb[frameInfo][i], GFP_ATOMIC); | |
717 | if (err) { | |
718 | dbg("%s %d\n", "submit urb error =", err); | |
719 | pdx->pendedPixelUrbs[frameInfo][i] = 0; | |
720 | return err; | |
f2d46e24 RG |
721 | } |
722 | pdx->pendedPixelUrbs[frameInfo][i] = 1; | |
28397ffe GKH |
723 | } |
724 | return 0; | |
725 | } | |
726 | ||
f2d46e24 | 727 | static const struct file_operations piusb_fops = { |
28397ffe GKH |
728 | .owner = THIS_MODULE, |
729 | .ioctl = piusb_ioctl, | |
730 | .open = piusb_open, | |
731 | .release = piusb_release, | |
732 | }; | |
733 | ||
734 | static struct usb_class_driver piusb_class = { | |
735 | .name = "usb/rspiusb%d", | |
736 | .fops = &piusb_fops, | |
737 | .minor_base = PIUSB_MINOR_BASE, | |
738 | }; | |
739 | ||
740 | /** | |
741 | * piusb_probe | |
742 | * | |
743 | * Called by the usb core when a new device is connected that it thinks | |
744 | * this driver might be interested in. | |
745 | */ | |
746 | static int piusb_probe(struct usb_interface *interface, | |
747 | const struct usb_device_id *id) | |
748 | { | |
749 | struct device_extension *pdx = NULL; | |
750 | struct usb_host_interface *iface_desc; | |
751 | struct usb_endpoint_descriptor *endpoint; | |
752 | int i; | |
753 | int retval = -ENOMEM; | |
754 | ||
755 | dev_dbg(&interface->dev, "%s - Looking for PI USB Hardware", __func__); | |
756 | ||
757 | pdx = kzalloc(sizeof(struct device_extension), GFP_KERNEL); | |
758 | if (pdx == NULL) { | |
759 | dev_err(&interface->dev, "Out of memory\n"); | |
760 | goto error; | |
761 | } | |
762 | kref_init(&pdx->kref); | |
763 | pdx->udev = usb_get_dev(interface_to_usbdev(interface)); | |
764 | pdx->interface = interface; | |
765 | iface_desc = interface->cur_altsetting; | |
766 | ||
767 | /* See if the device offered us matches what we can accept */ | |
768 | if ((pdx->udev->descriptor.idVendor != VENDOR_ID) | |
769 | || ((pdx->udev->descriptor.idProduct != PIXIS_PID) | |
f2d46e24 | 770 | && (pdx->udev->descriptor.idProduct != ST133_PID))) |
28397ffe | 771 | return -ENODEV; |
f2d46e24 | 772 | |
28397ffe GKH |
773 | pdx->iama = pdx->udev->descriptor.idProduct; |
774 | ||
775 | if (debug) { | |
776 | if (pdx->udev->descriptor.idProduct == PIXIS_PID) | |
777 | dbg("PIUSB:Pixis Camera Found"); | |
778 | else | |
779 | dbg("PIUSB:ST133 USB Controller Found"); | |
780 | if (pdx->udev->speed == USB_SPEED_HIGH) | |
781 | dbg("Highspeed(USB2.0) Device Attached"); | |
782 | else | |
783 | dbg("Lowspeed (USB1.1) Device Attached"); | |
784 | ||
785 | dbg("NumEndpoints in Configuration: %d", | |
786 | iface_desc->desc.bNumEndpoints); | |
787 | } | |
788 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | |
789 | endpoint = &iface_desc->endpoint[i].desc; | |
790 | if (debug) { | |
791 | dbg("Endpoint[%d]->bDescriptorType = %d", i, | |
792 | endpoint->bDescriptorType); | |
793 | dbg("Endpoint[%d]->bEndpointAddress = 0x%02X", i, | |
794 | endpoint->bEndpointAddress); | |
795 | dbg("Endpoint[%d]->bbmAttributes = %d", i, | |
796 | endpoint->bmAttributes); | |
797 | dbg("Endpoint[%d]->MaxPacketSize = %d\n", i, | |
798 | endpoint->wMaxPacketSize); | |
799 | } | |
c62d8437 JL |
800 | if (usb_endpoint_xfer_bulk(endpoint)) { |
801 | if (usb_endpoint_dir_in(endpoint)) | |
28397ffe GKH |
802 | pdx->hEP[i] = |
803 | usb_rcvbulkpipe(pdx->udev, | |
804 | endpoint->bEndpointAddress); | |
805 | else | |
806 | pdx->hEP[i] = | |
807 | usb_sndbulkpipe(pdx->udev, | |
808 | endpoint->bEndpointAddress); | |
809 | } | |
810 | } | |
811 | usb_set_intfdata(interface, pdx); | |
812 | retval = usb_register_dev(interface, &piusb_class); | |
813 | if (retval) { | |
814 | err("Not able to get a minor for this device."); | |
815 | usb_set_intfdata(interface, NULL); | |
816 | goto error; | |
817 | } | |
818 | pdx->present = 1; | |
819 | ||
820 | /* we can register the device now, as it is ready */ | |
821 | pdx->minor = interface->minor; | |
822 | /* let the user know what node this device is now attached to */ | |
823 | dbg("PI USB2.0 device now attached to piusb-%d", pdx->minor); | |
824 | return 0; | |
825 | ||
f2d46e24 | 826 | error: |
28397ffe GKH |
827 | if (pdx) |
828 | kref_put(&pdx->kref, piusb_delete); | |
829 | return retval; | |
830 | } | |
831 | ||
832 | /** | |
833 | * piusb_disconnect | |
834 | * | |
835 | * Called by the usb core when the device is removed from the system. | |
836 | * | |
837 | * This routine guarantees that the driver will not submit any more urbs | |
838 | * by clearing pdx->udev. It is also supposed to terminate any currently | |
839 | * active urbs. Unfortunately, usb_bulk_msg(), used in piusb_read(), does | |
840 | * not provide any way to do this. But at least we can cancel an active | |
841 | * write. | |
842 | */ | |
843 | static void piusb_disconnect(struct usb_interface *interface) | |
844 | { | |
845 | struct device_extension *pdx; | |
846 | int minor = interface->minor; | |
f2d46e24 | 847 | |
28397ffe | 848 | lock_kernel(); |
f2d46e24 | 849 | |
28397ffe GKH |
850 | pdx = usb_get_intfdata(interface); |
851 | usb_set_intfdata(interface, NULL); | |
f2d46e24 | 852 | |
28397ffe GKH |
853 | /* give back our minor */ |
854 | usb_deregister_dev(interface, &piusb_class); | |
f2d46e24 | 855 | |
28397ffe | 856 | unlock_kernel(); |
f2d46e24 | 857 | |
28397ffe GKH |
858 | /* prevent device read, write and ioctl */ |
859 | pdx->present = 0; | |
860 | kref_put(&pdx->kref, piusb_delete); | |
861 | dbg("PI USB2.0 device #%d now disconnected\n", minor); | |
862 | } | |
863 | ||
864 | static struct usb_driver piusb_driver = { | |
865 | .name = "sub", | |
866 | .probe = piusb_probe, | |
867 | .disconnect = piusb_disconnect, | |
868 | .id_table = pi_device_table, | |
869 | }; | |
870 | ||
871 | /** | |
872 | * piusb_init | |
873 | */ | |
874 | static int __init piusb_init(void) | |
875 | { | |
876 | int result; | |
f2d46e24 RG |
877 | |
878 | lastErr = 0; | |
879 | errCnt = 0; | |
880 | ||
28397ffe GKH |
881 | /* register this driver with the USB subsystem */ |
882 | result = usb_register(&piusb_driver); | |
f2d46e24 | 883 | if (result) |
28397ffe | 884 | printk(KERN_ERR KBUILD_MODNAME |
f2d46e24 RG |
885 | ": usb_register failed. Error number %d\n", |
886 | result); | |
887 | else | |
888 | printk(KERN_INFO KBUILD_MODNAME ":%s: %s\n", DRIVER_DESC, | |
889 | DRIVER_VERSION); | |
890 | return result; | |
28397ffe GKH |
891 | } |
892 | ||
893 | /** | |
894 | * piusb_exit | |
895 | */ | |
896 | static void __exit piusb_exit(void) | |
897 | { | |
898 | /* deregister this driver with the USB subsystem */ | |
899 | usb_deregister(&piusb_driver); | |
900 | } | |
901 | ||
902 | module_init(piusb_init); | |
903 | module_exit(piusb_exit); | |
904 | ||
905 | /* Module parameters */ | |
906 | module_param(debug, int, 0); | |
907 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | |
908 | ||
909 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
910 | MODULE_DESCRIPTION(DRIVER_DESC); | |
911 | MODULE_LICENSE("GPL v2"); |