1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 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 2 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 13 * the 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 20 * This is a kernel module for testing usb 21 * kernel functions found in /usr/src/<linux_ 22 * dir>/drivers/usb. The module is registered 23 * as a char device with the system so that 24 * ioctl calls can be made in a user space 25 * program that has attained the correct 26 * file descriptor for this module. A usb 27 * driver is registered with the system also 28 * so that it may be used in testing usb 29 * system calls. 30 * 31 * Reference: "Linux Device Drivers" by 32 * Alessandro Rubini and Jonathan Corbet 33 * 34 * Module name: tusb 35 * Author: Sean Ruyle (srruyle (at) us.ibm.com) 36 * Date: 6/2/2003 37 * 38 * tusb.c 39 */ 40 41 #include <linux/autoconf.h> 42 #include <linux/types.h> 43 #include <linux/kernel.h> 44 #include <linux/ioctl.h> 45 #include <linux/fs.h> 46 #include <linux/module.h> 47 #include <linux/init.h> 48 #include <linux/slab.h> 49 #include <linux/usb.h> 50 #include <linux/pci.h> 51 #include <linux/input.h> 52 #include <linux/types.h> 53 #include <linux/kdev_t.h> 54 #include <asm/uaccess.h> 55 56 #include "tusb.h" 57 #include "st_tusb.h" 58 59 MODULE_AUTHOR("Sean Ruyle <srruyle (at) us.ibm.com>"); 60 MODULE_DESCRIPTION(TEST_USB_DRIVER_NAME); 61 MODULE_LICENSE("GPL"); 62 63 static int tusb_ioctl(struct inode *, struct file *, unsigned int, 64 unsigned long); 65 static int tusb_open(struct inode *, struct file *); 66 static int tusb_close(struct inode *, struct file *); 67 68 static int test_find_usbdev(void); 69 static int test_find_hcd(void); 70 static int test_hcd_probe(void); 71 static int test_hcd_remove(void); 72 static int test_hcd_suspend(void); 73 static int test_hcd_resume(void); 74 /* 75 * File operations stuff 76 */ 77 static int Major = TUSB_MAJOR; 78 static tusb_user_t ltp_usb; 79 80 static struct file_operations tusb_fops = { 81 open: tusb_open, 82 release:tusb_close, 83 ioctl: tusb_ioctl, 84 }; 85 86 static int tusb_open(struct inode *ino, struct file *f) 87 { 88 return 0; 89 } 90 91 static int tusb_close(struct inode *ino, struct file *f) 92 { 93 return 0; 94 } 95 96 /* 97 * usb stuff 98 */ 99 struct tusb_device { 100 char name[128]; 101 char phys[64]; 102 struct usb_device *usbdev; 103 struct input_dev dev; 104 struct urb *irq; 105 int open; 106 107 signed char *data; 108 dma_addr_t data_dma; 109 }; 110 111 static void tusb_disconnect(struct usb_interface *intf) 112 { 113 printk("tusb: Entered disconnect function\n"); 114 } 115 116 static int tusb_probe(struct usb_interface *intf, 117 const struct usb_device_id *id) 118 { 119 printk("tusb: Entered probe function\n"); 120 return 0; 121 122 } 123 124 static struct usb_device_id tusb_id_table[] = { 125 { 126 USB_INTERFACE_INFO(3, 1, 1), 127 driver_info:(unsigned long)"keyboard"}, 128 { 129 USB_INTERFACE_INFO(3, 1, 2), 130 driver_info:(unsigned long)"mouse"}, 131 { 132 0, 133 } 134 }; 135 136 MODULE_DEVICE_TABLE(usb, tusb_id_table); 137 138 static struct usb_driver test_usb_driver = { 139 name: "tusb_two", 140 probe: tusb_probe, 141 disconnect:tusb_disconnect, 142 id_table:tusb_id_table, 143 }; 144 145 #if 0 146 static int test_alloc_dev(struct usb_device *dev) 147 { 148 printk("Entered test_alloc_dev\n"); 149 return 0; 150 } 151 152 static int test_dealloc_dev(struct usb_device *dev) 153 { 154 printk("Entered test_dealloc_dev\n"); 155 return 0; 156 } 157 158 static int test_get_current_frame_number(struct usb_device *dev) 159 { 160 printk("Entered test_get_current_frame_number\n"); 161 return 0; 162 } 163 164 static int test_submit_urb(struct urb *purb) 165 { 166 printk("Entered test_submit_urb\n"); 167 return 0; 168 } 169 170 static int test_unlink_urb(struct urb *purb) 171 { 172 printk("Entered test_unlink_urb\n"); 173 return 0; 174 } 175 176 static struct usb_operations test_device_operations = { 177 .allocate = test_alloc_dev, 178 .deallocate = test_dealloc_dev, 179 .get_frame_number = test_get_current_frame_number, 180 .submit_urb = test_submit_urb, 181 .unlink_urb = test_unlink_urb, 182 }; 183 #endif 184 185 static int tusb_ioctl(struct inode *ino, struct file *f, 186 unsigned int cmd, unsigned long l) 187 { 188 int rc; 189 tusb_interface_t tif; 190 caddr_t *inparms; 191 caddr_t *outparms; 192 193 printk("tusb: Entered the ioctl call\n"); 194 195 rc = 0; 196 inparms = NULL; 197 outparms = NULL; 198 199 if (copy_from_user(&tif, (void *)l, sizeof(tif))) { 200 /* Bad address */ 201 return (-EFAULT); 202 } 203 204 /* 205 * Setup inparms and outparms as needed 206 */ 207 if (tif.in_len > 0) { 208 inparms = (caddr_t *) kmalloc(tif.in_len, GFP_KERNEL); 209 if (!inparms) { 210 return (-ENOMEM); 211 } 212 213 rc = copy_from_user(inparms, tif.in_data, tif.in_len); 214 if (rc) { 215 kfree(inparms); 216 return (-EFAULT); 217 } 218 } 219 if (tif.out_len > 0) { 220 outparms = (caddr_t *) kmalloc(tif.out_len, GFP_KERNEL); 221 if (!outparms) { 222 kfree(inparms); 223 return (-ENOMEM); 224 } 225 } 226 227 switch (cmd) { 228 case FIND_DEV: 229 rc = test_find_usbdev(); 230 break; 231 case TEST_FIND_HCD: 232 rc = test_find_hcd(); 233 break; 234 case TEST_HCD_PROBE: 235 rc = test_hcd_probe(); 236 break; 237 case TEST_HCD_REMOVE: 238 rc = test_hcd_remove(); 239 break; 240 case TEST_HCD_SUSPEND: 241 rc = test_hcd_suspend(); 242 break; 243 case TEST_HCD_RESUME: 244 rc = test_hcd_resume(); 245 break; 246 default: 247 printk("Mismatching ioctl command\n"); 248 rc = 1; 249 break; 250 } 251 252 if (!ltp_usb.dev) 253 printk("tusb: After ioctl call dev DNE\n"); 254 255 /* 256 * copy in the return data, and test return code 257 */ 258 tif.out_rc = rc; 259 rc = 0; 260 261 /* if outparms then copy outparms into tif.out_data */ 262 if (outparms) { 263 if (copy_to_user(tif.out_data, outparms, tif.out_len)) { 264 printk("tpci: Unsuccessful copy_to_user of outparms\n"); 265 rc = -EFAULT; 266 } 267 } 268 269 /* copy tif structure into l so that can be used by user program */ 270 if (copy_to_user((void *)l, &tif, sizeof(tif))) { 271 printk("tpci: Unsuccessful copy_to_user of tif\n"); 272 rc = -EFAULT; 273 } 274 275 /* 276 * free inparms and outparms 277 */ 278 if (inparms) { 279 kfree(inparms); 280 } 281 if (outparms) { 282 kfree(outparms); 283 } 284 285 return rc; 286 } 287 288 /* 289 * test_find_usbdev 290 * using our driver, attempt to find 291 * a usb device that our driver can use, 292 * and set the pointers in our test interface 293 * structure to the device pointer so that 294 * it can be used future test calls 295 */ 296 static int test_find_usbdev() 297 { 298 struct usb_device *udev = 299 (struct usb_device *)kmalloc(sizeof(struct usb_device), GFP_KERNEL); 300 struct usb_bus *bus = 301 (struct usb_bus *)kmalloc(sizeof(struct usb_bus), GFP_KERNEL); 302 303 /* Zero out the ltp_usb */ 304 memset(<p_usb, 0, sizeof(tusb_user_t)); 305 306 ltp_usb.bus = bus; 307 ltp_usb.dev = udev; 308 309 /* allocate the usb_bus pointer */ 310 #if 0 311 bus = usb_alloc_bus(&test_device_operations); 312 if (!bus) { 313 printk("tusb: Did not allocate a bus\n"); 314 return 1; 315 } else { 316 printk("tusb: Allocated a bus pointer\n"); 317 memcpy(ltp_usb.bus, bus, sizeof(struct usb_bus)); 318 printk("test1\n"); 319 } 320 321 /* allocate the usb_device pointer */ 322 udev = usb_alloc_dev(NULL, bus); 323 if (udev) { 324 printk("tusb: Found a usb device pointer\n"); 325 memcpy(ltp_usb.dev, udev, sizeof(struct usb_device)); 326 } else { 327 printk("tusb: Failed find usb device pointer\n"); 328 return 1; 329 } 330 331 /* connect the new device and setup pointers */ 332 usb_connect(udev); 333 usb_new_device(udev); 334 #endif 335 336 return 0; 337 } 338 339 /* 340 * test_find_hcd 341 * make call to pci_find_class with correct flags 342 * to attempt to find a usb hostcontroller, that 343 * we can later use to test hcd functions, must 344 * have either uchi or ohci usb options enabled 345 * or will not find a device 346 */ 347 static int test_find_hcd() 348 { 349 struct pci_dev *pdev = 350 (struct pci_dev *)kmalloc(sizeof(struct pci_dev), GFP_KERNEL); 351 352 ltp_usb.pdev = pdev; 353 354 #if 0 355 /* try and get a usb hostcontroller if possible */ 356 pdev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, NULL); 357 if (pdev) { 358 printk("tusb: WOOT! Found a usb host controller!\n"); 359 printk("tusb: Slot number: %d\n", pdev->devfn); 360 361 memcpy(ltp_usb.pdev, pdev, sizeof(struct pci_dev)); 362 363 if (pdev->driver->id_table) 364 printk("tusb: id_table exists\n"); 365 366 return 0; 367 } else { 368 printk("tusb: Failed to find host controller\n"); 369 printk("tusb: Check kernel options enabled\n"); 370 return 1; 371 } 372 #else 373 return 1; 374 #endif 375 376 } 377 378 /* 379 * test_hcd_probe 380 * make call to usb_hcd_pci_probe which will 381 * enable the usb hostcontroller, pass in a pci_dev 382 * and a pci_device_id 383 */ 384 static int test_hcd_probe() 385 { 386 int rc; 387 struct usb_hcd *hcd = NULL; 388 struct pci_dev *pdev = ltp_usb.pdev; 389 struct pci_device_id *id = NULL; 390 391 if (!pdev) { 392 printk("tusb: pdev pointer not set\n"); 393 return 1; 394 } 395 396 id = (struct pci_device_id *)pdev->driver->id_table; 397 398 if (!id || !id->driver_data) { 399 printk("tusb: id_table not set\n"); 400 return 1; 401 } 402 403 /* release regions before probe call */ 404 hcd = pci_get_drvdata(pdev); 405 406 if (!hcd) { 407 printk("tusb: hcd pointer not found\n"); 408 return 1; 409 } else 410 release_region(pci_resource_start(pdev, hcd->region), 411 pci_resource_len(pdev, hcd->region)); 412 413 /* make test call */ 414 rc = usb_hcd_pci_probe(pdev, id); 415 416 if (rc) 417 printk("tusb: retval hcd probe = %d\n", rc); 418 else 419 printk("tusb: Success for usb_hcd_pci_probe\n"); 420 421 return rc; 422 } 423 424 /* 425 * test_hcd_remove 426 * make call to usb_hcd_pci_remove which will 427 * remove setup for the usb host controller 428 * from the system, attempting to call this 429 * before probe test call so that regions 430 * will be available to the probe test call 431 */ 432 static int test_hcd_remove() 433 { 434 struct pci_dev *pdev = NULL; 435 struct usb_hcd *hcd = NULL; 436 struct hc_driver *hdrv = NULL; 437 438 /* check that hcd pointer exists */ 439 if (!ltp_usb.pdev) { 440 printk("tusb: pdev pointer not found\n"); 441 return 1; 442 } else { 443 pdev = ltp_usb.pdev; 444 hcd = pci_get_drvdata(pdev); 445 } 446 447 if (!hdrv->stop) { 448 printk("tusb: stop function not found\n"); 449 return 1; 450 } else 451 hcd->driver->stop(hcd); 452 453 return 0; 454 } 455 456 /* 457 * test_hcd_suspend 458 * make call to suspend with a dev pointer and 459 * a u32 state variable that is the state to 460 * move into 461 */ 462 static int test_hcd_suspend() 463 { 464 int rc; 465 struct pci_dev *pdev = NULL; 466 467 /* check that pdev is set */ 468 if (!(pdev = ltp_usb.pdev)) { 469 printk("tusb: Cant find host controller pci_dev pointer\n"); 470 return 1; 471 } 472 473 /* make call and check return value */ 474 rc = usb_hcd_pci_suspend(pdev, (u32) 2); 475 if (rc) 476 printk("tusb: Suspend retval failure\n"); 477 else 478 printk("tusb: Suspend success\n"); 479 480 return rc; 481 } 482 483 /* 484 * test_hcd_resume 485 * make call to resume device for power management 486 * so that device will be active and able to use 487 * again 488 */ 489 static int test_hcd_resume() 490 { 491 int rc; 492 struct pci_dev *pdev = NULL; 493 494 /* check that pdev is set */ 495 if (!(pdev = ltp_usb.pdev)) { 496 printk("tusb: Cant find host controller pci_dev pointer\n"); 497 return 1; 498 } 499 500 /* make call and check return value */ 501 rc = usb_hcd_pci_resume(pdev); 502 if (rc) 503 printk("tusb: Resume got retval, failure\n"); 504 else 505 printk("tusb: Resume success\n"); 506 507 return rc; 508 } 509 510 static int tusb_init_module(void) 511 { 512 int rc; 513 514 SET_MODULE_OWNER(&tusb_fops); 515 516 rc = register_chrdev(Major, DEVICE_NAME, &tusb_fops); 517 if (rc < 0) { 518 printk("tusb: Failed to register tusb device\n"); 519 return rc; 520 } 521 522 if (Major == 0) 523 Major = rc; 524 525 printk("tusb: Registration success at major number %i\n", Major); 526 return usb_register(&test_usb_driver); 527 } 528 529 static void tusb_exit_module(void) 530 { 531 532 kfree(ltp_usb.dev); 533 534 #if 0 535 usb_free_bus(ltp_usb.bus); 536 #endif 537 538 unregister_chrdev(Major, DEVICE_NAME); 539 540 usb_deregister(&test_usb_driver); 541 } 542 543 module_init(tusb_init_module) 544 module_exit(tusb_exit_module) 545