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 14 15#include <linux/kernel.h> 16#include <linux/platform_device.h> 17#include <linux/list.h> 18#include <linux/module.h> 19#include <linux/usb/composite.h> 20#include <linux/usb/g_hid.h> 21 22#include "gadget_chips.h" 23#define DRIVER_DESC "HID Gadget" 24#define DRIVER_VERSION "2010/03/16" 25 26#include "u_hid.h" 27 28/*-------------------------------------------------------------------------*/ 29 30#define HIDG_VENDOR_NUM 0x0525 /* XXX NetChip */ 31#define HIDG_PRODUCT_NUM 0xa4ac /* Linux-USB HID gadget */ 32 33/*-------------------------------------------------------------------------*/ 34 35struct hidg_func_node { 36 struct usb_function_instance *fi; 37 struct usb_function *f; 38 struct list_head node; 39 struct hidg_func_descriptor *func; 40}; 41 42static LIST_HEAD(hidg_func_list); 43 44/*-------------------------------------------------------------------------*/ 45USB_GADGET_COMPOSITE_OPTIONS(); 46 47static struct usb_device_descriptor device_desc = { 48 .bLength = sizeof device_desc, 49 .bDescriptorType = USB_DT_DEVICE, 50 51 .bcdUSB = cpu_to_le16(0x0200), 52 53 /* .bDeviceClass = USB_CLASS_COMM, */ 54 /* .bDeviceSubClass = 0, */ 55 /* .bDeviceProtocol = 0, */ 56 .bDeviceClass = USB_CLASS_PER_INTERFACE, 57 .bDeviceSubClass = 0, 58 .bDeviceProtocol = 0, 59 /* .bMaxPacketSize0 = f(hardware) */ 60 61 /* Vendor and product id can be overridden by module parameters. */ 62 .idVendor = cpu_to_le16(HIDG_VENDOR_NUM), 63 .idProduct = cpu_to_le16(HIDG_PRODUCT_NUM), 64 /* .bcdDevice = f(hardware) */ 65 /* .iManufacturer = DYNAMIC */ 66 /* .iProduct = DYNAMIC */ 67 /* NO SERIAL NUMBER */ 68 .bNumConfigurations = 1, 69}; 70 71static struct usb_otg_descriptor otg_descriptor = { 72 .bLength = sizeof otg_descriptor, 73 .bDescriptorType = USB_DT_OTG, 74 75 /* REVISIT SRP-only hardware is possible, although 76 * it would not be called "OTG" ... 77 */ 78 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 79}; 80 81static const struct usb_descriptor_header *otg_desc[] = { 82 (struct usb_descriptor_header *) &otg_descriptor, 83 NULL, 84}; 85 86 87/* string IDs are assigned dynamically */ 88static struct usb_string strings_dev[] = { 89 [USB_GADGET_MANUFACTURER_IDX].s = "", 90 [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, 91 [USB_GADGET_SERIAL_IDX].s = "", 92 { } /* end of list */ 93}; 94 95static struct usb_gadget_strings stringtab_dev = { 96 .language = 0x0409, /* en-us */ 97 .strings = strings_dev, 98}; 99 100static struct usb_gadget_strings *dev_strings[] = { 101 &stringtab_dev, 102 NULL, 103}; 104 105 106 107/****************************** Configurations ******************************/ 108 109static int do_config(struct usb_configuration *c) 110{ 111 struct hidg_func_node *e, *n; 112 int status = 0; 113 114 if (gadget_is_otg(c->cdev->gadget)) { 115 c->descriptors = otg_desc; 116 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 117 } 118 119 list_for_each_entry(e, &hidg_func_list, node) { 120 e->f = usb_get_function(e->fi); 121 if (IS_ERR(e->f)) 122 goto put; 123 status = usb_add_function(c, e->f); 124 if (status < 0) { 125 usb_put_function(e->f); 126 goto put; 127 } 128 } 129 130 return 0; 131put: 132 list_for_each_entry(n, &hidg_func_list, node) { 133 if (n == e) 134 break; 135 usb_remove_function(c, n->f); 136 usb_put_function(n->f); 137 } 138 return status; 139} 140 141static struct usb_configuration config_driver = { 142 .label = "HID Gadget", 143 .bConfigurationValue = 1, 144 /* .iConfiguration = DYNAMIC */ 145 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 146}; 147 148/****************************** Gadget Bind ******************************/ 149 150static int hid_bind(struct usb_composite_dev *cdev) 151{ 152 struct usb_gadget *gadget = cdev->gadget; 153 struct list_head *tmp; 154 struct hidg_func_node *n, *m; 155 struct f_hid_opts *hid_opts; 156 int status, funcs = 0; 157 158 list_for_each(tmp, &hidg_func_list) 159 funcs++; 160 161 if (!funcs) 162 return -ENODEV; 163 164 list_for_each_entry(n, &hidg_func_list, node) { 165 n->fi = usb_get_function_instance("hid"); 166 if (IS_ERR(n->fi)) { 167 status = PTR_ERR(n->fi); 168 goto put; 169 } 170 hid_opts = container_of(n->fi, struct f_hid_opts, func_inst); 171 hid_opts->subclass = n->func->subclass; 172 hid_opts->protocol = n->func->protocol; 173 hid_opts->report_length = n->func->report_length; 174 hid_opts->report_desc_length = n->func->report_desc_length; 175 hid_opts->report_desc = n->func->report_desc; 176 } 177 178 179 /* Allocate string descriptor numbers ... note that string 180 * contents can be overridden by the composite_dev glue. 181 */ 182 183 status = usb_string_ids_tab(cdev, strings_dev); 184 if (status < 0) 185 goto put; 186 device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; 187 device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 188 189 /* register our configuration */ 190 status = usb_add_config(cdev, &config_driver, do_config); 191 if (status < 0) 192 goto put; 193 194 usb_composite_overwrite_options(cdev, &coverwrite); 195 dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); 196 197 return 0; 198 199put: 200 list_for_each_entry(m, &hidg_func_list, node) { 201 if (m == n) 202 break; 203 usb_put_function_instance(m->fi); 204 } 205 return status; 206} 207 208static int hid_unbind(struct usb_composite_dev *cdev) 209{ 210 struct hidg_func_node *n; 211 212 list_for_each_entry(n, &hidg_func_list, node) { 213 usb_put_function(n->f); 214 usb_put_function_instance(n->fi); 215 } 216 return 0; 217} 218 219static int hidg_plat_driver_probe(struct platform_device *pdev) 220{ 221 struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev); 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 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 .max_speed = USB_SPEED_HIGH, 260 .bind = hid_bind, 261 .unbind = hid_unbind, 262}; 263 264static struct platform_driver hidg_plat_driver = { 265 .remove = hidg_plat_driver_remove, 266 .driver = { 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_probe(&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 usb_composite_unregister(&hidg_driver); 296 platform_driver_unregister(&hidg_plat_driver); 297} 298module_exit(hidg_cleanup); 299