2 * g_dnl.c -- USB Downloader Gadget
4 * Copyright (C) 2012 Samsung Electronics
5 * Lukasz Majewski <l.majewski@samsung.com>
7 * SPDX-License-Identifier: GPL-2.0+
17 #include <usb_mass_storage.h>
21 #include "gadget_chips.h"
22 #include "composite.c"
25 * One needs to define the following:
26 * CONFIG_G_DNL_VENDOR_NUM
27 * CONFIG_G_DNL_PRODUCT_NUM
28 * CONFIG_G_DNL_MANUFACTURER
29 * at e.g. ./include/configs/<board>.h
32 #define STRING_MANUFACTURER 25
33 #define STRING_PRODUCT 2
34 /* Index of String Descriptor describing this configuration */
35 #define STRING_USBDOWN 2
36 /* Index of String serial */
37 #define STRING_SERIAL 3
38 #define MAX_STRING_SERIAL 32
39 /* Number of supported configurations */
40 #define CONFIGURATION_NUMBER 1
42 #define DRIVER_VERSION "usb_dnl 2.0"
44 static const char shortname
[] = "usb_dnl_";
45 static const char product
[] = "USB download gadget";
46 static char g_dnl_serial
[MAX_STRING_SERIAL
];
47 static const char manufacturer
[] = CONFIG_G_DNL_MANUFACTURER
;
49 void g_dnl_set_serialnumber(char *s
)
51 memset(g_dnl_serial
, 0, MAX_STRING_SERIAL
);
52 if (strlen(s
) < MAX_STRING_SERIAL
)
53 strncpy(g_dnl_serial
, s
, strlen(s
));
56 static struct usb_device_descriptor device_desc
= {
57 .bLength
= sizeof device_desc
,
58 .bDescriptorType
= USB_DT_DEVICE
,
60 .bcdUSB
= __constant_cpu_to_le16(0x0200),
61 .bDeviceClass
= USB_CLASS_COMM
,
62 .bDeviceSubClass
= 0x02, /*0x02:CDC-modem , 0x00:CDC-serial*/
64 .idVendor
= __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM
),
65 .idProduct
= __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM
),
66 .iProduct
= STRING_PRODUCT
,
67 .iSerialNumber
= STRING_SERIAL
,
68 .bNumConfigurations
= 1,
72 * static strings, in UTF-8
73 * IDs for those strings are assigned dynamically at g_dnl_bind()
75 static struct usb_string g_dnl_string_defs
[] = {
82 static struct usb_gadget_strings g_dnl_string_tab
= {
83 .language
= 0x0409, /* en-us */
84 .strings
= g_dnl_string_defs
,
87 static struct usb_gadget_strings
*g_dnl_composite_strings
[] = {
92 static int g_dnl_unbind(struct usb_composite_dev
*cdev
)
94 struct usb_gadget
*gadget
= cdev
->gadget
;
98 debug("%s: calling usb_gadget_disconnect for "
99 "controller '%s'\n", shortname
, gadget
->name
);
100 usb_gadget_disconnect(gadget
);
105 static int g_dnl_do_config(struct usb_configuration
*c
)
107 const char *s
= c
->cdev
->driver
->name
;
110 debug("%s: configuration: 0x%p composite dev: 0x%p\n",
111 __func__
, c
, c
->cdev
);
113 printf("GADGET DRIVER: %s\n", s
);
114 if (!strcmp(s
, "usb_dnl_dfu"))
116 else if (!strcmp(s
, "usb_dnl_ums"))
118 else if (!strcmp(s
, "usb_dnl_thor"))
124 static int g_dnl_config_register(struct usb_composite_dev
*cdev
)
126 struct usb_configuration
*config
;
127 const char *name
= "usb_dnload";
129 config
= memalign(CONFIG_SYS_CACHELINE_SIZE
, sizeof(*config
));
133 memset(config
, 0, sizeof(*config
));
135 config
->label
= name
;
136 config
->bmAttributes
= USB_CONFIG_ATT_ONE
| USB_CONFIG_ATT_SELFPOWER
;
137 config
->bConfigurationValue
= CONFIGURATION_NUMBER
;
138 config
->iConfiguration
= STRING_USBDOWN
;
139 config
->bind
= g_dnl_do_config
;
141 return usb_add_config(cdev
, config
);
145 int g_dnl_bind_fixup(struct usb_device_descriptor
*dev
, const char *name
)
150 __weak
int g_dnl_get_board_bcd_device_number(int gcnum
)
155 static int g_dnl_get_bcd_device_number(struct usb_composite_dev
*cdev
)
157 struct usb_gadget
*gadget
= cdev
->gadget
;
160 gcnum
= usb_gadget_controller_number(gadget
);
164 return g_dnl_get_board_bcd_device_number(gcnum
);
167 static int g_dnl_bind(struct usb_composite_dev
*cdev
)
169 struct usb_gadget
*gadget
= cdev
->gadget
;
173 debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__
, gadget
, cdev
);
175 id
= usb_string_id(cdev
);
179 g_dnl_string_defs
[0].id
= id
;
180 device_desc
.iManufacturer
= id
;
182 id
= usb_string_id(cdev
);
186 g_dnl_string_defs
[1].id
= id
;
187 device_desc
.iProduct
= id
;
189 id
= usb_string_id(cdev
);
193 g_dnl_string_defs
[2].id
= id
;
194 device_desc
.iSerialNumber
= id
;
196 g_dnl_bind_fixup(&device_desc
, cdev
->driver
->name
);
197 ret
= g_dnl_config_register(cdev
);
201 gcnum
= g_dnl_get_bcd_device_number(cdev
);
203 device_desc
.bcdDevice
= cpu_to_le16(gcnum
);
205 debug("%s: controller '%s' not recognized\n",
206 shortname
, gadget
->name
);
207 device_desc
.bcdDevice
= __constant_cpu_to_le16(0x9999);
210 debug("%s: calling usb_gadget_connect for "
211 "controller '%s'\n", shortname
, gadget
->name
);
212 usb_gadget_connect(gadget
);
221 static struct usb_composite_driver g_dnl_driver
= {
224 .strings
= g_dnl_composite_strings
,
227 .unbind
= g_dnl_unbind
,
230 int g_dnl_register(const char *type
)
232 /* The largest function name is 4 */
233 static char name
[sizeof(shortname
) + 4];
236 if (!strcmp(type
, "dfu")) {
237 strcpy(name
, shortname
);
239 } else if (!strcmp(type
, "ums")) {
240 strcpy(name
, shortname
);
242 } else if (!strcmp(type
, "thor")) {
243 strcpy(name
, shortname
);
246 printf("%s: unknown command: %s\n", __func__
, type
);
250 g_dnl_driver
.name
= name
;
252 debug("%s: g_dnl_driver.name: %s\n", __func__
, g_dnl_driver
.name
);
253 ret
= usb_composite_register(&g_dnl_driver
);
256 printf("%s: failed!, error: %d\n", __func__
, ret
);
263 void g_dnl_unregister(void)
265 usb_composite_unregister(&g_dnl_driver
);