aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/usb-skeleton.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/usb-skeleton.c')
-rw-r--r--drivers/usb/usb-skeleton.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 6c3a53f8f26c..5d02f16b7d0e 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -39,10 +39,15 @@ MODULE_DEVICE_TABLE (usb, skel_table);
39/* Get a minor range for your devices from the usb maintainer */ 39/* Get a minor range for your devices from the usb maintainer */
40#define USB_SKEL_MINOR_BASE 192 40#define USB_SKEL_MINOR_BASE 192
41 41
42/* our private defines. if this grows any larger, use your own .h file */
43#define MAX_TRANSFER ( PAGE_SIZE - 512 )
44#define WRITES_IN_FLIGHT 8
45
42/* Structure to hold all of our device specific stuff */ 46/* Structure to hold all of our device specific stuff */
43struct usb_skel { 47struct usb_skel {
44 struct usb_device * udev; /* the usb device for this device */ 48 struct usb_device * udev; /* the usb device for this device */
45 struct usb_interface * interface; /* the interface for this device */ 49 struct usb_interface * interface; /* the interface for this device */
50 struct semaphore limit_sem; /* limiting the number of writes in progress */
46 unsigned char * bulk_in_buffer; /* the buffer to receive data */ 51 unsigned char * bulk_in_buffer; /* the buffer to receive data */
47 size_t bulk_in_size; /* the size of the receive buffer */ 52 size_t bulk_in_size; /* the size of the receive buffer */
48 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ 53 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
@@ -152,6 +157,7 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
152 /* free up our allocated buffer */ 157 /* free up our allocated buffer */
153 usb_buffer_free(urb->dev, urb->transfer_buffer_length, 158 usb_buffer_free(urb->dev, urb->transfer_buffer_length,
154 urb->transfer_buffer, urb->transfer_dma); 159 urb->transfer_buffer, urb->transfer_dma);
160 up(&dev->limit_sem);
155} 161}
156 162
157static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) 163static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
@@ -160,6 +166,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
160 int retval = 0; 166 int retval = 0;
161 struct urb *urb = NULL; 167 struct urb *urb = NULL;
162 char *buf = NULL; 168 char *buf = NULL;
169 size_t writesize = min(count, (size_t)MAX_TRANSFER);
163 170
164 dev = (struct usb_skel *)file->private_data; 171 dev = (struct usb_skel *)file->private_data;
165 172
@@ -167,6 +174,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
167 if (count == 0) 174 if (count == 0)
168 goto exit; 175 goto exit;
169 176
177 /* limit the number of URBs in flight to stop a user from using up all RAM */
178 if (down_interruptible(&dev->limit_sem)) {
179 retval = -ERESTARTSYS;
180 goto exit;
181 }
182
170 /* create a urb, and a buffer for it, and copy the data to the urb */ 183 /* create a urb, and a buffer for it, and copy the data to the urb */
171 urb = usb_alloc_urb(0, GFP_KERNEL); 184 urb = usb_alloc_urb(0, GFP_KERNEL);
172 if (!urb) { 185 if (!urb) {
@@ -174,13 +187,13 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
174 goto error; 187 goto error;
175 } 188 }
176 189
177 buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); 190 buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
178 if (!buf) { 191 if (!buf) {
179 retval = -ENOMEM; 192 retval = -ENOMEM;
180 goto error; 193 goto error;
181 } 194 }
182 195
183 if (copy_from_user(buf, user_buffer, count)) { 196 if (copy_from_user(buf, user_buffer, writesize)) {
184 retval = -EFAULT; 197 retval = -EFAULT;
185 goto error; 198 goto error;
186 } 199 }
@@ -188,7 +201,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
188 /* initialize the urb properly */ 201 /* initialize the urb properly */
189 usb_fill_bulk_urb(urb, dev->udev, 202 usb_fill_bulk_urb(urb, dev->udev,
190 usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), 203 usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
191 buf, count, skel_write_bulk_callback, dev); 204 buf, writesize, skel_write_bulk_callback, dev);
192 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 205 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
193 206
194 /* send the data out the bulk port */ 207 /* send the data out the bulk port */
@@ -202,11 +215,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
202 usb_free_urb(urb); 215 usb_free_urb(urb);
203 216
204exit: 217exit:
205 return count; 218 return writesize;
206 219
207error: 220error:
208 usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); 221 usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
209 usb_free_urb(urb); 222 usb_free_urb(urb);
223 up(&dev->limit_sem);
210 return retval; 224 return retval;
211} 225}
212 226
@@ -238,13 +252,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
238 int retval = -ENOMEM; 252 int retval = -ENOMEM;
239 253
240 /* allocate memory for our device state and initialize it */ 254 /* allocate memory for our device state and initialize it */
241 dev = kmalloc(sizeof(*dev), GFP_KERNEL); 255 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
242 if (dev == NULL) { 256 if (dev == NULL) {
243 err("Out of memory"); 257 err("Out of memory");
244 goto error; 258 goto error;
245 } 259 }
246 memset(dev, 0x00, sizeof(*dev));
247 kref_init(&dev->kref); 260 kref_init(&dev->kref);
261 sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
248 262
249 dev->udev = usb_get_dev(interface_to_usbdev(interface)); 263 dev->udev = usb_get_dev(interface_to_usbdev(interface));
250 dev->interface = interface; 264 dev->interface = interface;
@@ -330,7 +344,6 @@ static void skel_disconnect(struct usb_interface *interface)
330} 344}
331 345
332static struct usb_driver skel_driver = { 346static struct usb_driver skel_driver = {
333 .owner = THIS_MODULE,
334 .name = "skeleton", 347 .name = "skeleton",
335 .probe = skel_probe, 348 .probe = skel_probe,
336 .disconnect = skel_disconnect, 349 .disconnect = skel_disconnect,