Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.0-rc6 669 lines 17 kB view raw
1/* 2 * f_hid.c -- USB HID function driver 3 * 4 * Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com> 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; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#include <linux/kernel.h> 22#include <linux/utsname.h> 23#include <linux/module.h> 24#include <linux/hid.h> 25#include <linux/cdev.h> 26#include <linux/mutex.h> 27#include <linux/poll.h> 28#include <linux/uaccess.h> 29#include <linux/wait.h> 30#include <linux/usb/g_hid.h> 31 32static int major, minors; 33static struct class *hidg_class; 34 35/*-------------------------------------------------------------------------*/ 36/* HID gadget struct */ 37 38struct f_hidg { 39 /* configuration */ 40 unsigned char bInterfaceSubClass; 41 unsigned char bInterfaceProtocol; 42 unsigned short report_desc_length; 43 char *report_desc; 44 unsigned short report_length; 45 46 /* recv report */ 47 char *set_report_buff; 48 unsigned short set_report_length; 49 spinlock_t spinlock; 50 wait_queue_head_t read_queue; 51 52 /* send report */ 53 struct mutex lock; 54 bool write_pending; 55 wait_queue_head_t write_queue; 56 struct usb_request *req; 57 58 int minor; 59 struct cdev cdev; 60 struct usb_function func; 61 struct usb_ep *in_ep; 62 struct usb_endpoint_descriptor *fs_in_ep_desc; 63 struct usb_endpoint_descriptor *hs_in_ep_desc; 64}; 65 66static inline struct f_hidg *func_to_hidg(struct usb_function *f) 67{ 68 return container_of(f, struct f_hidg, func); 69} 70 71/*-------------------------------------------------------------------------*/ 72/* Static descriptors */ 73 74static struct usb_interface_descriptor hidg_interface_desc = { 75 .bLength = sizeof hidg_interface_desc, 76 .bDescriptorType = USB_DT_INTERFACE, 77 /* .bInterfaceNumber = DYNAMIC */ 78 .bAlternateSetting = 0, 79 .bNumEndpoints = 1, 80 .bInterfaceClass = USB_CLASS_HID, 81 /* .bInterfaceSubClass = DYNAMIC */ 82 /* .bInterfaceProtocol = DYNAMIC */ 83 /* .iInterface = DYNAMIC */ 84}; 85 86static struct hid_descriptor hidg_desc = { 87 .bLength = sizeof hidg_desc, 88 .bDescriptorType = HID_DT_HID, 89 .bcdHID = 0x0101, 90 .bCountryCode = 0x00, 91 .bNumDescriptors = 0x1, 92 /*.desc[0].bDescriptorType = DYNAMIC */ 93 /*.desc[0].wDescriptorLenght = DYNAMIC */ 94}; 95 96/* High-Speed Support */ 97 98static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = { 99 .bLength = USB_DT_ENDPOINT_SIZE, 100 .bDescriptorType = USB_DT_ENDPOINT, 101 .bEndpointAddress = USB_DIR_IN, 102 .bmAttributes = USB_ENDPOINT_XFER_INT, 103 /*.wMaxPacketSize = DYNAMIC */ 104 .bInterval = 4, /* FIXME: Add this field in the 105 * HID gadget configuration? 106 * (struct hidg_func_descriptor) 107 */ 108}; 109 110static struct usb_descriptor_header *hidg_hs_descriptors[] = { 111 (struct usb_descriptor_header *)&hidg_interface_desc, 112 (struct usb_descriptor_header *)&hidg_desc, 113 (struct usb_descriptor_header *)&hidg_hs_in_ep_desc, 114 NULL, 115}; 116 117/* Full-Speed Support */ 118 119static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = { 120 .bLength = USB_DT_ENDPOINT_SIZE, 121 .bDescriptorType = USB_DT_ENDPOINT, 122 .bEndpointAddress = USB_DIR_IN, 123 .bmAttributes = USB_ENDPOINT_XFER_INT, 124 /*.wMaxPacketSize = DYNAMIC */ 125 .bInterval = 10, /* FIXME: Add this field in the 126 * HID gadget configuration? 127 * (struct hidg_func_descriptor) 128 */ 129}; 130 131static struct usb_descriptor_header *hidg_fs_descriptors[] = { 132 (struct usb_descriptor_header *)&hidg_interface_desc, 133 (struct usb_descriptor_header *)&hidg_desc, 134 (struct usb_descriptor_header *)&hidg_fs_in_ep_desc, 135 NULL, 136}; 137 138/*-------------------------------------------------------------------------*/ 139/* Char Device */ 140 141static ssize_t f_hidg_read(struct file *file, char __user *buffer, 142 size_t count, loff_t *ptr) 143{ 144 struct f_hidg *hidg = file->private_data; 145 char *tmp_buff = NULL; 146 unsigned long flags; 147 148 if (!count) 149 return 0; 150 151 if (!access_ok(VERIFY_WRITE, buffer, count)) 152 return -EFAULT; 153 154 spin_lock_irqsave(&hidg->spinlock, flags); 155 156#define READ_COND (hidg->set_report_buff != NULL) 157 158 while (!READ_COND) { 159 spin_unlock_irqrestore(&hidg->spinlock, flags); 160 if (file->f_flags & O_NONBLOCK) 161 return -EAGAIN; 162 163 if (wait_event_interruptible(hidg->read_queue, READ_COND)) 164 return -ERESTARTSYS; 165 166 spin_lock_irqsave(&hidg->spinlock, flags); 167 } 168 169 170 count = min_t(unsigned, count, hidg->set_report_length); 171 tmp_buff = hidg->set_report_buff; 172 hidg->set_report_buff = NULL; 173 174 spin_unlock_irqrestore(&hidg->spinlock, flags); 175 176 if (tmp_buff != NULL) { 177 /* copy to user outside spinlock */ 178 count -= copy_to_user(buffer, tmp_buff, count); 179 kfree(tmp_buff); 180 } else 181 count = -ENOMEM; 182 183 return count; 184} 185 186static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req) 187{ 188 struct f_hidg *hidg = (struct f_hidg *)ep->driver_data; 189 190 if (req->status != 0) { 191 ERROR(hidg->func.config->cdev, 192 "End Point Request ERROR: %d\n", req->status); 193 } 194 195 hidg->write_pending = 0; 196 wake_up(&hidg->write_queue); 197} 198 199static ssize_t f_hidg_write(struct file *file, const char __user *buffer, 200 size_t count, loff_t *offp) 201{ 202 struct f_hidg *hidg = file->private_data; 203 ssize_t status = -ENOMEM; 204 205 if (!access_ok(VERIFY_READ, buffer, count)) 206 return -EFAULT; 207 208 mutex_lock(&hidg->lock); 209 210#define WRITE_COND (!hidg->write_pending) 211 212 /* write queue */ 213 while (!WRITE_COND) { 214 mutex_unlock(&hidg->lock); 215 if (file->f_flags & O_NONBLOCK) 216 return -EAGAIN; 217 218 if (wait_event_interruptible_exclusive( 219 hidg->write_queue, WRITE_COND)) 220 return -ERESTARTSYS; 221 222 mutex_lock(&hidg->lock); 223 } 224 225 count = min_t(unsigned, count, hidg->report_length); 226 status = copy_from_user(hidg->req->buf, buffer, count); 227 228 if (status != 0) { 229 ERROR(hidg->func.config->cdev, 230 "copy_from_user error\n"); 231 mutex_unlock(&hidg->lock); 232 return -EINVAL; 233 } 234 235 hidg->req->status = 0; 236 hidg->req->zero = 0; 237 hidg->req->length = count; 238 hidg->req->complete = f_hidg_req_complete; 239 hidg->req->context = hidg; 240 hidg->write_pending = 1; 241 242 status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); 243 if (status < 0) { 244 ERROR(hidg->func.config->cdev, 245 "usb_ep_queue error on int endpoint %zd\n", status); 246 hidg->write_pending = 0; 247 wake_up(&hidg->write_queue); 248 } else { 249 status = count; 250 } 251 252 mutex_unlock(&hidg->lock); 253 254 return status; 255} 256 257static unsigned int f_hidg_poll(struct file *file, poll_table *wait) 258{ 259 struct f_hidg *hidg = file->private_data; 260 unsigned int ret = 0; 261 262 poll_wait(file, &hidg->read_queue, wait); 263 poll_wait(file, &hidg->write_queue, wait); 264 265 if (WRITE_COND) 266 ret |= POLLOUT | POLLWRNORM; 267 268 if (READ_COND) 269 ret |= POLLIN | POLLRDNORM; 270 271 return ret; 272} 273 274#undef WRITE_COND 275#undef READ_COND 276 277static int f_hidg_release(struct inode *inode, struct file *fd) 278{ 279 fd->private_data = NULL; 280 return 0; 281} 282 283static int f_hidg_open(struct inode *inode, struct file *fd) 284{ 285 struct f_hidg *hidg = 286 container_of(inode->i_cdev, struct f_hidg, cdev); 287 288 fd->private_data = hidg; 289 290 return 0; 291} 292 293/*-------------------------------------------------------------------------*/ 294/* usb_function */ 295 296static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) 297{ 298 struct f_hidg *hidg = (struct f_hidg *)req->context; 299 300 if (req->status != 0 || req->buf == NULL || req->actual == 0) { 301 ERROR(hidg->func.config->cdev, "%s FAILED\n", __func__); 302 return; 303 } 304 305 spin_lock(&hidg->spinlock); 306 307 hidg->set_report_buff = krealloc(hidg->set_report_buff, 308 req->actual, GFP_ATOMIC); 309 310 if (hidg->set_report_buff == NULL) { 311 spin_unlock(&hidg->spinlock); 312 return; 313 } 314 hidg->set_report_length = req->actual; 315 memcpy(hidg->set_report_buff, req->buf, req->actual); 316 317 spin_unlock(&hidg->spinlock); 318 319 wake_up(&hidg->read_queue); 320} 321 322static int hidg_setup(struct usb_function *f, 323 const struct usb_ctrlrequest *ctrl) 324{ 325 struct f_hidg *hidg = func_to_hidg(f); 326 struct usb_composite_dev *cdev = f->config->cdev; 327 struct usb_request *req = cdev->req; 328 int status = 0; 329 __u16 value, length; 330 331 value = __le16_to_cpu(ctrl->wValue); 332 length = __le16_to_cpu(ctrl->wLength); 333 334 VDBG(cdev, "hid_setup crtl_request : bRequestType:0x%x bRequest:0x%x " 335 "Value:0x%x\n", ctrl->bRequestType, ctrl->bRequest, value); 336 337 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { 338 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 339 | HID_REQ_GET_REPORT): 340 VDBG(cdev, "get_report\n"); 341 342 /* send an empty report */ 343 length = min_t(unsigned, length, hidg->report_length); 344 memset(req->buf, 0x0, length); 345 346 goto respond; 347 break; 348 349 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 350 | HID_REQ_GET_PROTOCOL): 351 VDBG(cdev, "get_protocol\n"); 352 goto stall; 353 break; 354 355 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 356 | HID_REQ_SET_REPORT): 357 VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength); 358 req->context = hidg; 359 req->complete = hidg_set_report_complete; 360 goto respond; 361 break; 362 363 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 364 | HID_REQ_SET_PROTOCOL): 365 VDBG(cdev, "set_protocol\n"); 366 goto stall; 367 break; 368 369 case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8 370 | USB_REQ_GET_DESCRIPTOR): 371 switch (value >> 8) { 372 case HID_DT_REPORT: 373 VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n"); 374 length = min_t(unsigned short, length, 375 hidg->report_desc_length); 376 memcpy(req->buf, hidg->report_desc, length); 377 goto respond; 378 break; 379 380 default: 381 VDBG(cdev, "Unknown decriptor request 0x%x\n", 382 value >> 8); 383 goto stall; 384 break; 385 } 386 break; 387 388 default: 389 VDBG(cdev, "Unknown request 0x%x\n", 390 ctrl->bRequest); 391 goto stall; 392 break; 393 } 394 395stall: 396 return -EOPNOTSUPP; 397 398respond: 399 req->zero = 0; 400 req->length = length; 401 status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); 402 if (status < 0) 403 ERROR(cdev, "usb_ep_queue error on ep0 %d\n", value); 404 return status; 405} 406 407static void hidg_disable(struct usb_function *f) 408{ 409 struct f_hidg *hidg = func_to_hidg(f); 410 411 usb_ep_disable(hidg->in_ep); 412 hidg->in_ep->driver_data = NULL; 413} 414 415static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) 416{ 417 struct usb_composite_dev *cdev = f->config->cdev; 418 struct f_hidg *hidg = func_to_hidg(f); 419 const struct usb_endpoint_descriptor *ep_desc; 420 int status = 0; 421 422 VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt); 423 424 if (hidg->in_ep != NULL) { 425 /* restart endpoint */ 426 if (hidg->in_ep->driver_data != NULL) 427 usb_ep_disable(hidg->in_ep); 428 429 ep_desc = ep_choose(f->config->cdev->gadget, 430 hidg->hs_in_ep_desc, hidg->fs_in_ep_desc); 431 status = usb_ep_enable(hidg->in_ep, ep_desc); 432 if (status < 0) { 433 ERROR(cdev, "Enable endpoint FAILED!\n"); 434 goto fail; 435 } 436 hidg->in_ep->driver_data = hidg; 437 } 438fail: 439 return status; 440} 441 442const struct file_operations f_hidg_fops = { 443 .owner = THIS_MODULE, 444 .open = f_hidg_open, 445 .release = f_hidg_release, 446 .write = f_hidg_write, 447 .read = f_hidg_read, 448 .poll = f_hidg_poll, 449 .llseek = noop_llseek, 450}; 451 452static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) 453{ 454 struct usb_ep *ep; 455 struct f_hidg *hidg = func_to_hidg(f); 456 int status; 457 dev_t dev; 458 459 /* allocate instance-specific interface IDs, and patch descriptors */ 460 status = usb_interface_id(c, f); 461 if (status < 0) 462 goto fail; 463 hidg_interface_desc.bInterfaceNumber = status; 464 465 466 /* allocate instance-specific endpoints */ 467 status = -ENODEV; 468 ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc); 469 if (!ep) 470 goto fail; 471 ep->driver_data = c->cdev; /* claim */ 472 hidg->in_ep = ep; 473 474 /* preallocate request and buffer */ 475 status = -ENOMEM; 476 hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL); 477 if (!hidg->req) 478 goto fail; 479 480 481 hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL); 482 if (!hidg->req->buf) 483 goto fail; 484 485 /* set descriptor dynamic values */ 486 hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass; 487 hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; 488 hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); 489 hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); 490 hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT; 491 hidg_desc.desc[0].wDescriptorLength = 492 cpu_to_le16(hidg->report_desc_length); 493 494 hidg->set_report_buff = NULL; 495 496 /* copy descriptors */ 497 f->descriptors = usb_copy_descriptors(hidg_fs_descriptors); 498 if (!f->descriptors) 499 goto fail; 500 501 hidg->fs_in_ep_desc = usb_find_endpoint(hidg_fs_descriptors, 502 f->descriptors, 503 &hidg_fs_in_ep_desc); 504 505 if (gadget_is_dualspeed(c->cdev->gadget)) { 506 hidg_hs_in_ep_desc.bEndpointAddress = 507 hidg_fs_in_ep_desc.bEndpointAddress; 508 f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors); 509 if (!f->hs_descriptors) 510 goto fail; 511 hidg->hs_in_ep_desc = usb_find_endpoint(hidg_hs_descriptors, 512 f->hs_descriptors, 513 &hidg_hs_in_ep_desc); 514 } else { 515 hidg->hs_in_ep_desc = NULL; 516 } 517 518 mutex_init(&hidg->lock); 519 spin_lock_init(&hidg->spinlock); 520 init_waitqueue_head(&hidg->write_queue); 521 init_waitqueue_head(&hidg->read_queue); 522 523 /* create char device */ 524 cdev_init(&hidg->cdev, &f_hidg_fops); 525 dev = MKDEV(major, hidg->minor); 526 status = cdev_add(&hidg->cdev, dev, 1); 527 if (status) 528 goto fail; 529 530 device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor); 531 532 return 0; 533 534fail: 535 ERROR(f->config->cdev, "hidg_bind FAILED\n"); 536 if (hidg->req != NULL) { 537 kfree(hidg->req->buf); 538 if (hidg->in_ep != NULL) 539 usb_ep_free_request(hidg->in_ep, hidg->req); 540 } 541 542 usb_free_descriptors(f->hs_descriptors); 543 usb_free_descriptors(f->descriptors); 544 545 return status; 546} 547 548static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) 549{ 550 struct f_hidg *hidg = func_to_hidg(f); 551 552 device_destroy(hidg_class, MKDEV(major, hidg->minor)); 553 cdev_del(&hidg->cdev); 554 555 /* disable/free request and end point */ 556 usb_ep_disable(hidg->in_ep); 557 usb_ep_dequeue(hidg->in_ep, hidg->req); 558 kfree(hidg->req->buf); 559 usb_ep_free_request(hidg->in_ep, hidg->req); 560 561 /* free descriptors copies */ 562 usb_free_descriptors(f->hs_descriptors); 563 usb_free_descriptors(f->descriptors); 564 565 kfree(hidg->report_desc); 566 kfree(hidg->set_report_buff); 567 kfree(hidg); 568} 569 570/*-------------------------------------------------------------------------*/ 571/* Strings */ 572 573#define CT_FUNC_HID_IDX 0 574 575static struct usb_string ct_func_string_defs[] = { 576 [CT_FUNC_HID_IDX].s = "HID Interface", 577 {}, /* end of list */ 578}; 579 580static struct usb_gadget_strings ct_func_string_table = { 581 .language = 0x0409, /* en-US */ 582 .strings = ct_func_string_defs, 583}; 584 585static struct usb_gadget_strings *ct_func_strings[] = { 586 &ct_func_string_table, 587 NULL, 588}; 589 590/*-------------------------------------------------------------------------*/ 591/* usb_configuration */ 592 593int __init hidg_bind_config(struct usb_configuration *c, 594 struct hidg_func_descriptor *fdesc, int index) 595{ 596 struct f_hidg *hidg; 597 int status; 598 599 if (index >= minors) 600 return -ENOENT; 601 602 /* maybe allocate device-global string IDs, and patch descriptors */ 603 if (ct_func_string_defs[CT_FUNC_HID_IDX].id == 0) { 604 status = usb_string_id(c->cdev); 605 if (status < 0) 606 return status; 607 ct_func_string_defs[CT_FUNC_HID_IDX].id = status; 608 hidg_interface_desc.iInterface = status; 609 } 610 611 /* allocate and initialize one new instance */ 612 hidg = kzalloc(sizeof *hidg, GFP_KERNEL); 613 if (!hidg) 614 return -ENOMEM; 615 616 hidg->minor = index; 617 hidg->bInterfaceSubClass = fdesc->subclass; 618 hidg->bInterfaceProtocol = fdesc->protocol; 619 hidg->report_length = fdesc->report_length; 620 hidg->report_desc_length = fdesc->report_desc_length; 621 hidg->report_desc = kmemdup(fdesc->report_desc, 622 fdesc->report_desc_length, 623 GFP_KERNEL); 624 if (!hidg->report_desc) { 625 kfree(hidg); 626 return -ENOMEM; 627 } 628 629 hidg->func.name = "hid"; 630 hidg->func.strings = ct_func_strings; 631 hidg->func.bind = hidg_bind; 632 hidg->func.unbind = hidg_unbind; 633 hidg->func.set_alt = hidg_set_alt; 634 hidg->func.disable = hidg_disable; 635 hidg->func.setup = hidg_setup; 636 637 status = usb_add_function(c, &hidg->func); 638 if (status) 639 kfree(hidg); 640 641 return status; 642} 643 644int __init ghid_setup(struct usb_gadget *g, int count) 645{ 646 int status; 647 dev_t dev; 648 649 hidg_class = class_create(THIS_MODULE, "hidg"); 650 651 status = alloc_chrdev_region(&dev, 0, count, "hidg"); 652 if (!status) { 653 major = MAJOR(dev); 654 minors = count; 655 } 656 657 return status; 658} 659 660void ghid_cleanup(void) 661{ 662 if (major) { 663 unregister_chrdev_region(MKDEV(major, 0), minors); 664 major = minors = 0; 665 } 666 667 class_destroy(hidg_class); 668 hidg_class = NULL; 669}