Krishna iResearch Intelligent Cloud Platform - USB-md - Modified USB Driver
 All Classes
umb.c
1 /******************************************************************************************************
2 * UMB - Universal Modified Bus Driver - simple USB driver for debugging
3 * created date: 1 Feb 2013
4 * updated on : 25 Feb 2014
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
17 *
18 * --------------------------------------------------------------------------------------------------
19 * Copyright (C):
20 * Srinivasan Kannan (alias) Ka.Shrinivaasan (alias) Shrinivas Kannan
21 * Independent Open Source Developer, Researcher and Consultant
22 * Ph: 9789346927, 9003082186, 9791165980
23 * Open Source Products Profile(Krishna iResearch):
24 * http://sourceforge.net/users/ka_shrinivaasan,
25 * https://www.ohloh.net/accounts/ka_shrinivaasan
26 * Personal website(research): https://sites.google.com/site/kuja27/
27 * emails: ka.shrinivaasan@gmail.com, shrinivas.kannan@gmail.com, kashrinivaasan@live.com
28 * --------------------------------------------------------------------------------------------------
29 ********************************************************************************************************/
30 
31 /*
32 *##########################################################################################
33 * References, copyright attributions and quotes :
34 * 1. Linux Device Driver 3rd edition example USB driver source code
35 * 2. Understanding Linux Kernel 3rd edition
36 * 3. Various USB debugging resources
37 *
38 * Copyright attribution from Linux Device Driver 3rd edition :
39 * USB Skeleton driver - 2.0
40 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
41 *
42 * This program is free software; you can redistribute it and/or
43 * modify it under the terms of the GNU General Public License as
44 * published by the Free Software Foundation, version 2.
45 *
46 * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
47 * but has been rewritten to be easy to read and use, as no locks are now
48 * needed anymore.
49 ************************************************************************************************************
50 */
51 
52 /*
53  * Changes done for Linux Kernel 3.2.0 and 3.7.8:
54  * 1.Removed BigKernelLock(BKL) and replaced it with a mutex
55  * 2.Replaced usb_buffer_alloc() with usb_buffer_coherent
56  * 3.Build errors fixed
57  */
58 
59 /*
60 #include <linux/config.h>
61 #include <linux/smp_lock.h>
62 */
63 #include <linux/mutex.h>
64 #include <linux/kernel.h>
65 #include <linux/errno.h>
66 #include <linux/init.h>
67 #include <linux/slab.h>
68 #include <linux/module.h>
69 #include <linux/kref.h>
70 #include <linux/usb.h>
71 #include <asm/uaccess.h>
72 
73 #define to_umb_driver(d) container_of(d, struct usb_umb, kref)
74 
75 /*
76 #define UMB_VENDOR_ID 0xcde0
77 #define UMB_PRODUCT_ID 0xabc0
78 */
79 
80 /*
81 * SanDisk
82 *--------
83 */
84 
85 /*
86 #define UMB_VENDOR_ID 0x0781
87 #define UMB_PRODUCT_ID 0x5567
88 */
89 
90 #define UMB_VENDOR_ID 0x12d1
91 #define UMB_PRODUCT_ID 0x140b
92 
93 struct mutex umb_mutex;
94 
95 MODULE_LICENSE("GPL");
96 
97 static struct usb_device_id umb_table[] = {
98  { USB_DEVICE(UMB_VENDOR_ID, UMB_PRODUCT_ID)},
99  /*{.driver_info = 42},*/
100  { }
101 };
102 
103 /*MODULE_DEVICE_TABLE(usb, umb_table);*/
104 
105 static ssize_t umb_read(struct file* f, char __user *buffer, size_t count, loff_t* ppos);
106 static ssize_t umb_write(struct file *f, const char __user *user_buffer, size_t count, loff_t *ppos);
107 static void umb_probe(struct usb_interface *interface, const struct usb_device_id* id);
108 static void umb_disconnect(struct usb_interface *interface);
109 static int umb_release(struct inode* inode, struct file* file);
110 static void umb_delete(struct kref* kref);
111 static int umb_open(struct inode* inode, struct file* file);
112 static char* umb_devnode(struct device *dev, mode_t *mode);
113 
114 #define USB_UMB_MINOR_BASE 378
115 
116 static struct usb_driver umb_driver = {
117  .name = "umb",
118  .id_table = umb_table,
119  .probe = umb_probe,
120  .disconnect = umb_disconnect
121 };
122 
123 static struct file_operations umb_fops = {
124  .owner = THIS_MODULE,
125  .read = umb_read,
126  .write = umb_write,
127  .open = umb_open,
128  .release = umb_release
129 };
130 
131 /*
132  * umb_devnode callback added
133  * - 12 Feb 2013 ka.shrinivaasan@gmail.com
134  */
135 static struct usb_class_driver umb_class = {
136  /*
137  _class_register() requires name to be set due to printk in drivers/base/class.c
138  - Ka.Shrinivaasan 27 February 2014
139  */
140  .name = "usb/umb%d",
141  .fops = &umb_fops,
142  /*.mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,*/
143  /*.devnode = umb_devnode,*/
144  /*.minor_base = USB_UMB_MINOR_BASE,*/
145 };
146 
147 struct usb_umb {
148  struct usb_device* udev;
149  struct usb_interface* interface;
150  unsigned char* bulk_in_buffer;
151  /*
152  * bulk_out_buffer added
153  * - ka.shrinivaasan 8 Feb 2013
154  */
155  unsigned char* bulk_out_buffer;
156  size_t bulk_in_size;
157  __u8 bulk_in_endpointAddr;
158  __u8 bulk_out_endpointAddr;
159  struct kref kref;
160 };
161 
162 static ssize_t umb_read(struct file* f, char __user *buffer, size_t count, loff_t* ppos)
163 {
164  struct usb_umb *dev;
165  int retval = 0;
166 
167  printk(KERN_INFO "umb_read(): before usb_bulk_msg\n");
168  dev = (struct usb_umb*)f->private_data;
169  retval = usb_bulk_msg(dev->udev,
170  usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
171  dev->bulk_in_buffer,
172  min(dev->bulk_in_size, count),
173  &count,
174  HZ*10
175  );
176  printk(KERN_INFO "umb_read(): before copy_to_user(): dev->bulk_in_buffer=%s\n", dev->bulk_in_buffer);
177  copy_to_user(buffer, dev->bulk_in_buffer, count);
178  return retval;
179 
180 }
181 
182 static void umb_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
183 {
184  /*Fix for Linux kernel 3.7.8 build error*/
185  /*dbg("in function %s and urb status is %d \n", __FUNCTION__, urb->status);*/
186  printk(KERN_INFO "in function %s and urb status is %d \n", urb->status);
187 }
188 
189 static ssize_t umb_write(struct file *f, const char __user *user_buffer, size_t count, loff_t *ppos)
190 {
191  struct usb_umb *dev;
192  int retval = 0;
193  struct urb *urb = NULL;
194  char *buf = NULL;
195 
196  printk(KERN_INFO "umb_write(): before usb_alloc_urb\n");
197  dev = (struct usb_umb*)f->private_data;
198 
199  if (count == 0)
200  return -1;
201 
202  /*alloc urb and buffer, copy from userspace*/
203  urb = usb_alloc_urb(0, GFP_ATOMIC);
204  /*buf = usb_buffer_alloc(dev->udev, count, GFP_ATOMIC, &urb->transfer_dma);*/
205  buf = usb_alloc_coherent(dev->udev, count, GFP_ATOMIC, &urb->transfer_dma);
206  printk(KERN_INFO "umb_write(): before copy_from_user(): buf=%s\n", buf);
207  copy_from_user(buf, user_buffer, count);
208 
209  /*fill urb and submit */
210  usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
211  buf, count, umb_write_bulk_callback, dev);
212  urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
213  retval = usb_submit_urb(urb, GFP_ATOMIC);
214  usb_free_urb(urb);
215  return count;
216 }
217 
218 static char* umb_devnode(struct device *dev, mode_t *mode)
219 {
220  return "mode";
221 }
222 
223 static int umb_init(void)
224 {
225  int result;
226  result = usb_register(&umb_driver);
227  printk(KERN_INFO "umb_init(): in init ...after usb_register(), result %d\n", result);
228  return result;
229 }
230 
231 static void umb_exit(void)
232 {
233  usb_deregister(&umb_driver);
234  printk(KERN_INFO "umb_exit(): in exit\n");
235  return 0;
236 }
237 
238 static void umb_probe(struct usb_interface *interface, const struct usb_device_id* id)
239 {
240  struct usb_umb* dev=NULL;
241  struct usb_host_interface* iface_desc;
242  struct usb_endpoint_descriptor* endpoint;
243  size_t buffer_size;
244  int i;
245  int retval = -ENOMEM;
246 
247  printk(KERN_INFO "umb_probe(): before probing\n");
248  dev=kzalloc(sizeof(struct usb_umb), GFP_ATOMIC);
249  memset(dev, 0x0, sizeof(struct usb_umb));
250  printk(KERN_INFO "umb_probe(): before kref_init\n");
251  kref_init(&dev->kref);
252 
253  printk(KERN_INFO "umb_probe(): before usb_get_dev\n");
254  dev->udev = usb_get_dev(interface_to_usbdev(interface));
255  dev->interface = interface;
256 
257  iface_desc = interface->cur_altsetting;
258  for(i=0; i < iface_desc->desc.bNumEndpoints; i++)
259  {
260  printk(KERN_INFO "umb_probe(): looping over interface endpoints: i= %d\n",i);
261  endpoint = &iface_desc->endpoint[i].desc;
262  if(!dev->bulk_in_endpointAddr &&
263  (endpoint->bEndpointAddress & USB_DIR_IN) &&
264  ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
265  == USB_ENDPOINT_XFER_BULK))
266  {
267  printk(KERN_INFO "umb_probe(): before initializing dev bulk in data\n");
268  buffer_size = endpoint->wMaxPacketSize;
269  dev->bulk_in_size = buffer_size;
270  dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
271  dev->bulk_in_buffer = kzalloc(buffer_size, GFP_ATOMIC);
272  }
273  if(!dev->bulk_out_endpointAddr &&
274  (endpoint->bEndpointAddress & USB_DIR_OUT) &&
275  ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
276  == USB_ENDPOINT_XFER_BULK))
277  {
278  printk(KERN_INFO "umb_probe(): before allocating dev bulk out data\n");
279  dev->bulk_out_buffer = kzalloc(buffer_size,GFP_ATOMIC);
280  dev->bulk_out_endpointAddr= endpoint->bEndpointAddress;
281  }
282  }
283  printk(KERN_INFO "umb_probe(): before usb_set_intfdata\n");
284  usb_set_intfdata(interface, dev);
285  printk(KERN_INFO "umb_probe(): before usb_register_dev, interface=%p, umb_class=%p\n", interface, &umb_class);
286  usb_register_dev(interface, &umb_class);
287  return 0;
288 }
289 
290 static void umb_disconnect(struct usb_interface *interface)
291 {
292  struct usb_umb *dev;
293  int minor = interface->minor;
294 
295  /*
296  commenting mutex lock and unlock due to crash in mutex_lock_slow_path which is already an open
297  bug filed in a previous linux version. Could be related.
298  -Ka.Shrinivaasan 5March2014
299  */
300 
301  /*lock_kernel();*/
302  /*mutex_lock(&umb_mutex);*/
303  printk(KERN_INFO "umb_disconnect(): before deregistering device");
304  dev = usb_get_intfdata(interface);
305  usb_set_intfdata(interface,NULL);
306  usb_deregister_dev(interface, &umb_class);
307  /*unlock_kernel();*/
308  /*mutex_unlock(&umb_mutex);*/
309  kref_put(&dev->kref, umb_delete);
310 }
311 
312 static int umb_open(struct inode* inode, struct file* file)
313 {
314  struct usb_umb *dev;
315  struct usb_interface *interface;
316  int subminor;
317  int retval = 0;
318 
319  subminor = iminor(inode);
320 
321  interface = usb_find_interface(&umb_driver, subminor);
322  dev = usb_get_intfdata(interface);
323 
324  kref_get(&dev->kref);
325 
326  file->private_data = dev;
327  return retval;
328 }
329 
330 static int umb_release(struct inode* inode, struct file* file)
331 {
332  struct usb_umb *dev;
333  dev = (struct usb_umb*)file->private_data;
334  kref_put(&dev->kref, umb_delete);
335 }
336 
337 static void umb_delete(struct kref* kref)
338 {
339  struct usb_umb* dev = to_umb_driver(kref);
340  usb_put_dev(dev->udev);
341  kfree(dev->bulk_in_buffer);
342  kfree(dev);
343 }
344 
345 module_init(umb_init);
346 module_exit(umb_exit);
347 
Definition: umb.c:147