at v3.1 297 lines 7.3 kB view raw
1/* 2 * hid.c -- HID Composite driver 3 * 4 * Based on multi.c 5 * 6 * Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 24#include <linux/kernel.h> 25#include <linux/platform_device.h> 26#include <linux/list.h> 27 28#define DRIVER_DESC "HID Gadget" 29#define DRIVER_VERSION "2010/03/16" 30 31/*-------------------------------------------------------------------------*/ 32 33#define HIDG_VENDOR_NUM 0x0525 /* XXX NetChip */ 34#define HIDG_PRODUCT_NUM 0xa4ac /* Linux-USB HID gadget */ 35 36/*-------------------------------------------------------------------------*/ 37 38/* 39 * kbuild is not very cooperative with respect to linking separately 40 * compiled library objects into one module. So for now we won't use 41 * separate compilation ... ensuring init/exit sections work to shrink 42 * the runtime footprint, and giving us at least some parts of what 43 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 44 */ 45 46#include "composite.c" 47#include "usbstring.c" 48#include "config.c" 49#include "epautoconf.c" 50 51#include "f_hid.c" 52 53 54struct hidg_func_node { 55 struct list_head node; 56 struct hidg_func_descriptor *func; 57}; 58 59static LIST_HEAD(hidg_func_list); 60 61/*-------------------------------------------------------------------------*/ 62 63static struct usb_device_descriptor device_desc = { 64 .bLength = sizeof device_desc, 65 .bDescriptorType = USB_DT_DEVICE, 66 67 .bcdUSB = cpu_to_le16(0x0200), 68 69 /* .bDeviceClass = USB_CLASS_COMM, */ 70 /* .bDeviceSubClass = 0, */ 71 /* .bDeviceProtocol = 0, */ 72 .bDeviceClass = 0xEF, 73 .bDeviceSubClass = 2, 74 .bDeviceProtocol = 1, 75 /* .bMaxPacketSize0 = f(hardware) */ 76 77 /* Vendor and product id can be overridden by module parameters. */ 78 .idVendor = cpu_to_le16(HIDG_VENDOR_NUM), 79 .idProduct = cpu_to_le16(HIDG_PRODUCT_NUM), 80 /* .bcdDevice = f(hardware) */ 81 /* .iManufacturer = DYNAMIC */ 82 /* .iProduct = DYNAMIC */ 83 /* NO SERIAL NUMBER */ 84 .bNumConfigurations = 1, 85}; 86 87static struct usb_otg_descriptor otg_descriptor = { 88 .bLength = sizeof otg_descriptor, 89 .bDescriptorType = USB_DT_OTG, 90 91 /* REVISIT SRP-only hardware is possible, although 92 * it would not be called "OTG" ... 93 */ 94 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 95}; 96 97static const struct usb_descriptor_header *otg_desc[] = { 98 (struct usb_descriptor_header *) &otg_descriptor, 99 NULL, 100}; 101 102 103/* string IDs are assigned dynamically */ 104 105#define STRING_MANUFACTURER_IDX 0 106#define STRING_PRODUCT_IDX 1 107 108static char manufacturer[50]; 109 110static struct usb_string strings_dev[] = { 111 [STRING_MANUFACTURER_IDX].s = manufacturer, 112 [STRING_PRODUCT_IDX].s = DRIVER_DESC, 113 { } /* end of list */ 114}; 115 116static struct usb_gadget_strings stringtab_dev = { 117 .language = 0x0409, /* en-us */ 118 .strings = strings_dev, 119}; 120 121static struct usb_gadget_strings *dev_strings[] = { 122 &stringtab_dev, 123 NULL, 124}; 125 126 127 128/****************************** Configurations ******************************/ 129 130static int __init do_config(struct usb_configuration *c) 131{ 132 struct hidg_func_node *e; 133 int func = 0, status = 0; 134 135 if (gadget_is_otg(c->cdev->gadget)) { 136 c->descriptors = otg_desc; 137 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 138 } 139 140 list_for_each_entry(e, &hidg_func_list, node) { 141 status = hidg_bind_config(c, e->func, func++); 142 if (status) 143 break; 144 } 145 146 return status; 147} 148 149static struct usb_configuration config_driver = { 150 .label = "HID Gadget", 151 .bConfigurationValue = 1, 152 /* .iConfiguration = DYNAMIC */ 153 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 154}; 155 156/****************************** Gadget Bind ******************************/ 157 158static int __init hid_bind(struct usb_composite_dev *cdev) 159{ 160 struct usb_gadget *gadget = cdev->gadget; 161 struct list_head *tmp; 162 int status, gcnum, funcs = 0; 163 164 list_for_each(tmp, &hidg_func_list) 165 funcs++; 166 167 if (!funcs) 168 return -ENODEV; 169 170 /* set up HID */ 171 status = ghid_setup(cdev->gadget, funcs); 172 if (status < 0) 173 return status; 174 175 gcnum = usb_gadget_controller_number(gadget); 176 if (gcnum >= 0) 177 device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); 178 else 179 device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); 180 181 182 /* Allocate string descriptor numbers ... note that string 183 * contents can be overridden by the composite_dev glue. 184 */ 185 186 /* device descriptor strings: manufacturer, product */ 187 snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", 188 init_utsname()->sysname, init_utsname()->release, 189 gadget->name); 190 status = usb_string_id(cdev); 191 if (status < 0) 192 return status; 193 strings_dev[STRING_MANUFACTURER_IDX].id = status; 194 device_desc.iManufacturer = status; 195 196 status = usb_string_id(cdev); 197 if (status < 0) 198 return status; 199 strings_dev[STRING_PRODUCT_IDX].id = status; 200 device_desc.iProduct = status; 201 202 /* register our configuration */ 203 status = usb_add_config(cdev, &config_driver, do_config); 204 if (status < 0) 205 return status; 206 207 dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); 208 209 return 0; 210} 211 212static int __exit hid_unbind(struct usb_composite_dev *cdev) 213{ 214 ghid_cleanup(); 215 return 0; 216} 217 218static int __init hidg_plat_driver_probe(struct platform_device *pdev) 219{ 220 struct hidg_func_descriptor *func = pdev->dev.platform_data; 221 struct hidg_func_node *entry; 222 223 if (!func) { 224 dev_err(&pdev->dev, "Platform data missing\n"); 225 return -ENODEV; 226 } 227 228 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 229 if (!entry) 230 return -ENOMEM; 231 232 entry->func = func; 233 list_add_tail(&entry->node, &hidg_func_list); 234 235 return 0; 236} 237 238static int __devexit hidg_plat_driver_remove(struct platform_device *pdev) 239{ 240 struct hidg_func_node *e, *n; 241 242 list_for_each_entry_safe(e, n, &hidg_func_list, node) { 243 list_del(&e->node); 244 kfree(e); 245 } 246 247 return 0; 248} 249 250 251/****************************** Some noise ******************************/ 252 253 254static struct usb_composite_driver hidg_driver = { 255 .name = "g_hid", 256 .dev = &device_desc, 257 .strings = dev_strings, 258 .max_speed = USB_SPEED_HIGH, 259 .unbind = __exit_p(hid_unbind), 260}; 261 262static struct platform_driver hidg_plat_driver = { 263 .remove = __devexit_p(hidg_plat_driver_remove), 264 .driver = { 265 .owner = THIS_MODULE, 266 .name = "hidg", 267 }, 268}; 269 270 271MODULE_DESCRIPTION(DRIVER_DESC); 272MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard"); 273MODULE_LICENSE("GPL"); 274 275static int __init hidg_init(void) 276{ 277 int status; 278 279 status = platform_driver_probe(&hidg_plat_driver, 280 hidg_plat_driver_probe); 281 if (status < 0) 282 return status; 283 284 status = usb_composite_probe(&hidg_driver, hid_bind); 285 if (status < 0) 286 platform_driver_unregister(&hidg_plat_driver); 287 288 return status; 289} 290module_init(hidg_init); 291 292static void __exit hidg_cleanup(void) 293{ 294 platform_driver_unregister(&hidg_plat_driver); 295 usb_composite_unregister(&hidg_driver); 296} 297module_exit(hidg_cleanup);