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 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 __ref 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 .bind = do_config, 152 .bConfigurationValue = 1, 153 /* .iConfiguration = DYNAMIC */ 154 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 155}; 156 157/****************************** Gadget Bind ******************************/ 158 159static int __ref hid_bind(struct usb_composite_dev *cdev) 160{ 161 struct usb_gadget *gadget = cdev->gadget; 162 struct list_head *tmp; 163 int status, gcnum, funcs = 0; 164 165 list_for_each(tmp, &hidg_func_list) 166 funcs++; 167 168 if (!funcs) 169 return -ENODEV; 170 171 /* set up HID */ 172 status = ghid_setup(cdev->gadget, funcs); 173 if (status < 0) 174 return status; 175 176 gcnum = usb_gadget_controller_number(gadget); 177 if (gcnum >= 0) 178 device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); 179 else 180 device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); 181 182 183 /* Allocate string descriptor numbers ... note that string 184 * contents can be overridden by the composite_dev glue. 185 */ 186 187 /* device descriptor strings: manufacturer, product */ 188 snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", 189 init_utsname()->sysname, init_utsname()->release, 190 gadget->name); 191 status = usb_string_id(cdev); 192 if (status < 0) 193 return status; 194 strings_dev[STRING_MANUFACTURER_IDX].id = status; 195 device_desc.iManufacturer = status; 196 197 status = usb_string_id(cdev); 198 if (status < 0) 199 return status; 200 strings_dev[STRING_PRODUCT_IDX].id = status; 201 device_desc.iProduct = status; 202 203 /* register our configuration */ 204 status = usb_add_config(cdev, &config_driver); 205 if (status < 0) 206 return status; 207 208 dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); 209 210 return 0; 211} 212 213static int __exit hid_unbind(struct usb_composite_dev *cdev) 214{ 215 ghid_cleanup(); 216 return 0; 217} 218 219static int __init hidg_plat_driver_probe(struct platform_device *pdev) 220{ 221 struct hidg_func_descriptor *func = pdev->dev.platform_data; 222 struct hidg_func_node *entry; 223 224 if (!func) { 225 dev_err(&pdev->dev, "Platform data missing\n"); 226 return -ENODEV; 227 } 228 229 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 230 if (!entry) 231 return -ENOMEM; 232 233 entry->func = func; 234 list_add_tail(&entry->node, &hidg_func_list); 235 236 return 0; 237} 238 239static int __devexit hidg_plat_driver_remove(struct platform_device *pdev) 240{ 241 struct hidg_func_node *e, *n; 242 243 list_for_each_entry_safe(e, n, &hidg_func_list, node) { 244 list_del(&e->node); 245 kfree(e); 246 } 247 248 return 0; 249} 250 251 252/****************************** Some noise ******************************/ 253 254 255static struct usb_composite_driver hidg_driver = { 256 .name = "g_hid", 257 .dev = &device_desc, 258 .strings = dev_strings, 259 .bind = hid_bind, 260 .unbind = __exit_p(hid_unbind), 261}; 262 263static struct platform_driver hidg_plat_driver = { 264 .remove = __devexit_p(hidg_plat_driver_remove), 265 .driver = { 266 .owner = THIS_MODULE, 267 .name = "hidg", 268 }, 269}; 270 271 272MODULE_DESCRIPTION(DRIVER_DESC); 273MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard"); 274MODULE_LICENSE("GPL"); 275 276static int __init hidg_init(void) 277{ 278 int status; 279 280 status = platform_driver_probe(&hidg_plat_driver, 281 hidg_plat_driver_probe); 282 if (status < 0) 283 return status; 284 285 status = usb_composite_register(&hidg_driver); 286 if (status < 0) 287 platform_driver_unregister(&hidg_plat_driver); 288 289 return status; 290} 291module_init(hidg_init); 292 293static void __exit hidg_cleanup(void) 294{ 295 platform_driver_unregister(&hidg_plat_driver); 296 usb_composite_unregister(&hidg_driver); 297} 298module_exit(hidg_cleanup); 299