Commit d6eae7b0b172b3ef31a3f816ce946857f382ac4e
Committed by
Marek Vasut
1 parent
7b412ab31f
Exists in
master
and in
50 other branches
usb:g_dnl: Add name parameter to g_dnl_bind_fixup function
New parameter, namely *name has been added to g_dnl_bind_fixup(). It is necessary (for compatibility reasons) to assign new USB idProduct and idVendor for different usb functions. Signed-off-by: Lukasz Majewski <l.majewski@samsung.com> Cc: Marek Vasut <marex@denx.de>
Showing 3 changed files with 4 additions and 4 deletions Inline Diff
board/siemens/common/factoryset.c
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * Read FactorySet information from EEPROM into global structure. | 3 | * Read FactorySet information from EEPROM into global structure. |
4 | * (C) Copyright 2013 Siemens Schweiz AG | 4 | * (C) Copyright 2013 Siemens Schweiz AG |
5 | * | 5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | 6 | * SPDX-License-Identifier: GPL-2.0+ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #if !defined(CONFIG_SPL_BUILD) | 9 | #if !defined(CONFIG_SPL_BUILD) |
10 | 10 | ||
11 | #include <common.h> | 11 | #include <common.h> |
12 | #include <i2c.h> | 12 | #include <i2c.h> |
13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
14 | #include <asm/arch/cpu.h> | 14 | #include <asm/arch/cpu.h> |
15 | #include <asm/arch/sys_proto.h> | 15 | #include <asm/arch/sys_proto.h> |
16 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
17 | #include <net.h> | 17 | #include <net.h> |
18 | #include <usbdescriptors.h> | 18 | #include <usbdescriptors.h> |
19 | #include "factoryset.h" | 19 | #include "factoryset.h" |
20 | 20 | ||
21 | #define EEPR_PG_SZ 0x80 | 21 | #define EEPR_PG_SZ 0x80 |
22 | #define EEPROM_FATORYSET_OFFSET 0x400 | 22 | #define EEPROM_FATORYSET_OFFSET 0x400 |
23 | #define OFF_PG EEPROM_FATORYSET_OFFSET/EEPR_PG_SZ | 23 | #define OFF_PG EEPROM_FATORYSET_OFFSET/EEPR_PG_SZ |
24 | 24 | ||
25 | /* Global variable that contains necessary information from FactorySet */ | 25 | /* Global variable that contains necessary information from FactorySet */ |
26 | struct factorysetcontainer factory_dat; | 26 | struct factorysetcontainer factory_dat; |
27 | 27 | ||
28 | #define fact_get_char(i) *((char *)&eeprom_buf[i]) | 28 | #define fact_get_char(i) *((char *)&eeprom_buf[i]) |
29 | 29 | ||
30 | static int fact_match(unsigned char *eeprom_buf, uchar *s1, int i2) | 30 | static int fact_match(unsigned char *eeprom_buf, uchar *s1, int i2) |
31 | { | 31 | { |
32 | if (s1 == NULL) | 32 | if (s1 == NULL) |
33 | return -1; | 33 | return -1; |
34 | 34 | ||
35 | while (*s1 == fact_get_char(i2++)) | 35 | while (*s1 == fact_get_char(i2++)) |
36 | if (*s1++ == '=') | 36 | if (*s1++ == '=') |
37 | return i2; | 37 | return i2; |
38 | 38 | ||
39 | if (*s1 == '\0' && fact_get_char(i2-1) == '=') | 39 | if (*s1 == '\0' && fact_get_char(i2-1) == '=') |
40 | return i2; | 40 | return i2; |
41 | 41 | ||
42 | return -1; | 42 | return -1; |
43 | } | 43 | } |
44 | 44 | ||
45 | static int get_factory_val(unsigned char *eeprom_buf, int size, uchar *name, | 45 | static int get_factory_val(unsigned char *eeprom_buf, int size, uchar *name, |
46 | uchar *buf, int len) | 46 | uchar *buf, int len) |
47 | { | 47 | { |
48 | int i, nxt = 0; | 48 | int i, nxt = 0; |
49 | 49 | ||
50 | for (i = 0; fact_get_char(i) != '\0'; i = nxt + 1) { | 50 | for (i = 0; fact_get_char(i) != '\0'; i = nxt + 1) { |
51 | int val, n; | 51 | int val, n; |
52 | 52 | ||
53 | for (nxt = i; fact_get_char(nxt) != '\0'; ++nxt) { | 53 | for (nxt = i; fact_get_char(nxt) != '\0'; ++nxt) { |
54 | if (nxt >= size) | 54 | if (nxt >= size) |
55 | return -1; | 55 | return -1; |
56 | } | 56 | } |
57 | 57 | ||
58 | val = fact_match(eeprom_buf, (uchar *)name, i); | 58 | val = fact_match(eeprom_buf, (uchar *)name, i); |
59 | if (val < 0) | 59 | if (val < 0) |
60 | continue; | 60 | continue; |
61 | 61 | ||
62 | /* found; copy out */ | 62 | /* found; copy out */ |
63 | for (n = 0; n < len; ++n, ++buf) { | 63 | for (n = 0; n < len; ++n, ++buf) { |
64 | *buf = fact_get_char(val++); | 64 | *buf = fact_get_char(val++); |
65 | if (*buf == '\0') | 65 | if (*buf == '\0') |
66 | return n; | 66 | return n; |
67 | } | 67 | } |
68 | 68 | ||
69 | if (n) | 69 | if (n) |
70 | *--buf = '\0'; | 70 | *--buf = '\0'; |
71 | 71 | ||
72 | printf("env_buf [%d bytes] too small for value of \"%s\"\n", | 72 | printf("env_buf [%d bytes] too small for value of \"%s\"\n", |
73 | len, name); | 73 | len, name); |
74 | 74 | ||
75 | return n; | 75 | return n; |
76 | } | 76 | } |
77 | return -1; | 77 | return -1; |
78 | } | 78 | } |
79 | 79 | ||
80 | static | 80 | static |
81 | int get_factory_record_val(unsigned char *eeprom_buf, int size, uchar *record, | 81 | int get_factory_record_val(unsigned char *eeprom_buf, int size, uchar *record, |
82 | uchar *name, uchar *buf, int len) | 82 | uchar *name, uchar *buf, int len) |
83 | { | 83 | { |
84 | int ret = -1; | 84 | int ret = -1; |
85 | int i, nxt = 0; | 85 | int i, nxt = 0; |
86 | int c; | 86 | int c; |
87 | unsigned char end = 0xff; | 87 | unsigned char end = 0xff; |
88 | 88 | ||
89 | for (i = 0; fact_get_char(i) != end; i = nxt) { | 89 | for (i = 0; fact_get_char(i) != end; i = nxt) { |
90 | nxt = i + 1; | 90 | nxt = i + 1; |
91 | if (fact_get_char(i) == '>') { | 91 | if (fact_get_char(i) == '>') { |
92 | int pos; | 92 | int pos; |
93 | int endpos; | 93 | int endpos; |
94 | int z; | 94 | int z; |
95 | 95 | ||
96 | c = strncmp((char *)&eeprom_buf[i + 1], (char *)record, | 96 | c = strncmp((char *)&eeprom_buf[i + 1], (char *)record, |
97 | strlen((char *)record)); | 97 | strlen((char *)record)); |
98 | if (c == 0) { | 98 | if (c == 0) { |
99 | /* record found */ | 99 | /* record found */ |
100 | pos = i + strlen((char *)record) + 2; | 100 | pos = i + strlen((char *)record) + 2; |
101 | nxt = pos; | 101 | nxt = pos; |
102 | /* search for "<" */ | 102 | /* search for "<" */ |
103 | c = -1; | 103 | c = -1; |
104 | for (z = pos; fact_get_char(z) != end; z++) { | 104 | for (z = pos; fact_get_char(z) != end; z++) { |
105 | if ((fact_get_char(z) == '<') || | 105 | if ((fact_get_char(z) == '<') || |
106 | (fact_get_char(z) == '>')) { | 106 | (fact_get_char(z) == '>')) { |
107 | endpos = z; | 107 | endpos = z; |
108 | nxt = endpos; | 108 | nxt = endpos; |
109 | c = 0; | 109 | c = 0; |
110 | break; | 110 | break; |
111 | } | 111 | } |
112 | } | 112 | } |
113 | } | 113 | } |
114 | if (c == 0) { | 114 | if (c == 0) { |
115 | /* end found -> call get_factory_val */ | 115 | /* end found -> call get_factory_val */ |
116 | eeprom_buf[endpos] = end; | 116 | eeprom_buf[endpos] = end; |
117 | ret = get_factory_val(&eeprom_buf[pos], | 117 | ret = get_factory_val(&eeprom_buf[pos], |
118 | size - pos, name, buf, len); | 118 | size - pos, name, buf, len); |
119 | /* fix buffer */ | 119 | /* fix buffer */ |
120 | eeprom_buf[endpos] = '<'; | 120 | eeprom_buf[endpos] = '<'; |
121 | debug("%s: %s.%s = %s\n", | 121 | debug("%s: %s.%s = %s\n", |
122 | __func__, record, name, buf); | 122 | __func__, record, name, buf); |
123 | return ret; | 123 | return ret; |
124 | } | 124 | } |
125 | } | 125 | } |
126 | } | 126 | } |
127 | return ret; | 127 | return ret; |
128 | } | 128 | } |
129 | 129 | ||
130 | int factoryset_read_eeprom(int i2c_addr) | 130 | int factoryset_read_eeprom(int i2c_addr) |
131 | { | 131 | { |
132 | int i, pages = 0, size = 0; | 132 | int i, pages = 0, size = 0; |
133 | unsigned char eeprom_buf[0x3c00], hdr[4], buf[MAX_STRING_LENGTH]; | 133 | unsigned char eeprom_buf[0x3c00], hdr[4], buf[MAX_STRING_LENGTH]; |
134 | unsigned char *cp, *cp1; | 134 | unsigned char *cp, *cp1; |
135 | 135 | ||
136 | #if defined(CONFIG_DFU_FUNCTION) | 136 | #if defined(CONFIG_DFU_FUNCTION) |
137 | factory_dat.usb_vendor_id = CONFIG_G_DNL_VENDOR_NUM; | 137 | factory_dat.usb_vendor_id = CONFIG_G_DNL_VENDOR_NUM; |
138 | factory_dat.usb_product_id = CONFIG_G_DNL_PRODUCT_NUM; | 138 | factory_dat.usb_product_id = CONFIG_G_DNL_PRODUCT_NUM; |
139 | #endif | 139 | #endif |
140 | if (i2c_probe(i2c_addr)) | 140 | if (i2c_probe(i2c_addr)) |
141 | goto err; | 141 | goto err; |
142 | 142 | ||
143 | if (i2c_read(i2c_addr, EEPROM_FATORYSET_OFFSET, 2, hdr, sizeof(hdr))) | 143 | if (i2c_read(i2c_addr, EEPROM_FATORYSET_OFFSET, 2, hdr, sizeof(hdr))) |
144 | goto err; | 144 | goto err; |
145 | 145 | ||
146 | if ((hdr[0] != 0x99) || (hdr[1] != 0x80)) { | 146 | if ((hdr[0] != 0x99) || (hdr[1] != 0x80)) { |
147 | printf("FactorySet is not right in eeprom.\n"); | 147 | printf("FactorySet is not right in eeprom.\n"); |
148 | return 1; | 148 | return 1; |
149 | } | 149 | } |
150 | 150 | ||
151 | /* get FactorySet size */ | 151 | /* get FactorySet size */ |
152 | size = (hdr[2] << 8) + hdr[3] + sizeof(hdr); | 152 | size = (hdr[2] << 8) + hdr[3] + sizeof(hdr); |
153 | if (size > 0x3bfa) | 153 | if (size > 0x3bfa) |
154 | size = 0x3bfa; | 154 | size = 0x3bfa; |
155 | 155 | ||
156 | pages = size / EEPR_PG_SZ; | 156 | pages = size / EEPR_PG_SZ; |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * read the eeprom using i2c | 159 | * read the eeprom using i2c |
160 | * I can not read entire eeprom in once, so separate into several | 160 | * I can not read entire eeprom in once, so separate into several |
161 | * times. Furthermore, fetch eeprom take longer time, so we fetch | 161 | * times. Furthermore, fetch eeprom take longer time, so we fetch |
162 | * data after every time we got a record from eeprom | 162 | * data after every time we got a record from eeprom |
163 | */ | 163 | */ |
164 | debug("Read eeprom page :\n"); | 164 | debug("Read eeprom page :\n"); |
165 | for (i = 0; i < pages; i++) | 165 | for (i = 0; i < pages; i++) |
166 | if (i2c_read(i2c_addr, (OFF_PG + i) * EEPR_PG_SZ, 2, | 166 | if (i2c_read(i2c_addr, (OFF_PG + i) * EEPR_PG_SZ, 2, |
167 | eeprom_buf + (i * EEPR_PG_SZ), EEPR_PG_SZ)) | 167 | eeprom_buf + (i * EEPR_PG_SZ), EEPR_PG_SZ)) |
168 | goto err; | 168 | goto err; |
169 | 169 | ||
170 | if (size % EEPR_PG_SZ) | 170 | if (size % EEPR_PG_SZ) |
171 | if (i2c_read(i2c_addr, (OFF_PG + pages) * EEPR_PG_SZ, 2, | 171 | if (i2c_read(i2c_addr, (OFF_PG + pages) * EEPR_PG_SZ, 2, |
172 | eeprom_buf + (pages * EEPR_PG_SZ), | 172 | eeprom_buf + (pages * EEPR_PG_SZ), |
173 | (size % EEPR_PG_SZ))) | 173 | (size % EEPR_PG_SZ))) |
174 | goto err; | 174 | goto err; |
175 | 175 | ||
176 | /* we do below just for eeprom align */ | 176 | /* we do below just for eeprom align */ |
177 | for (i = 0; i < size; i++) | 177 | for (i = 0; i < size; i++) |
178 | if (eeprom_buf[i] == '\n') | 178 | if (eeprom_buf[i] == '\n') |
179 | eeprom_buf[i] = 0; | 179 | eeprom_buf[i] = 0; |
180 | 180 | ||
181 | /* skip header */ | 181 | /* skip header */ |
182 | size -= sizeof(hdr); | 182 | size -= sizeof(hdr); |
183 | cp = (uchar *)eeprom_buf + sizeof(hdr); | 183 | cp = (uchar *)eeprom_buf + sizeof(hdr); |
184 | 184 | ||
185 | /* get mac address */ | 185 | /* get mac address */ |
186 | get_factory_record_val(cp, size, (uchar *)"ETH1", (uchar *)"mac", | 186 | get_factory_record_val(cp, size, (uchar *)"ETH1", (uchar *)"mac", |
187 | buf, MAX_STRING_LENGTH); | 187 | buf, MAX_STRING_LENGTH); |
188 | cp1 = buf; | 188 | cp1 = buf; |
189 | for (i = 0; i < 6; i++) { | 189 | for (i = 0; i < 6; i++) { |
190 | factory_dat.mac[i] = simple_strtoul((char *)cp1, NULL, 16); | 190 | factory_dat.mac[i] = simple_strtoul((char *)cp1, NULL, 16); |
191 | cp1 += 3; | 191 | cp1 += 3; |
192 | } | 192 | } |
193 | 193 | ||
194 | #if defined(CONFIG_DFU_FUNCTION) | 194 | #if defined(CONFIG_DFU_FUNCTION) |
195 | /* read vid and pid for dfu mode */ | 195 | /* read vid and pid for dfu mode */ |
196 | if (0 <= get_factory_record_val(cp, size, (uchar *)"USBD1", | 196 | if (0 <= get_factory_record_val(cp, size, (uchar *)"USBD1", |
197 | (uchar *)"vid", buf, | 197 | (uchar *)"vid", buf, |
198 | MAX_STRING_LENGTH)) { | 198 | MAX_STRING_LENGTH)) { |
199 | factory_dat.usb_vendor_id = simple_strtoul((char *)buf, | 199 | factory_dat.usb_vendor_id = simple_strtoul((char *)buf, |
200 | NULL, 16); | 200 | NULL, 16); |
201 | } | 201 | } |
202 | 202 | ||
203 | if (0 <= get_factory_record_val(cp, size, (uchar *)"USBD1", | 203 | if (0 <= get_factory_record_val(cp, size, (uchar *)"USBD1", |
204 | (uchar *)"pid", buf, | 204 | (uchar *)"pid", buf, |
205 | MAX_STRING_LENGTH)) { | 205 | MAX_STRING_LENGTH)) { |
206 | factory_dat.usb_product_id = simple_strtoul((char *)buf, | 206 | factory_dat.usb_product_id = simple_strtoul((char *)buf, |
207 | NULL, 16); | 207 | NULL, 16); |
208 | } | 208 | } |
209 | printf("DFU USB: VID = 0x%4x, PID = 0x%4x\n", factory_dat.usb_vendor_id, | 209 | printf("DFU USB: VID = 0x%4x, PID = 0x%4x\n", factory_dat.usb_vendor_id, |
210 | factory_dat.usb_product_id); | 210 | factory_dat.usb_product_id); |
211 | #endif | 211 | #endif |
212 | if (0 <= get_factory_record_val(cp, size, (uchar *)"DEV", | 212 | if (0 <= get_factory_record_val(cp, size, (uchar *)"DEV", |
213 | (uchar *)"id", buf, | 213 | (uchar *)"id", buf, |
214 | MAX_STRING_LENGTH)) { | 214 | MAX_STRING_LENGTH)) { |
215 | if (strncmp((const char *)buf, "PXM50", 5) == 0) | 215 | if (strncmp((const char *)buf, "PXM50", 5) == 0) |
216 | factory_dat.pxm50 = 1; | 216 | factory_dat.pxm50 = 1; |
217 | else | 217 | else |
218 | factory_dat.pxm50 = 0; | 218 | factory_dat.pxm50 = 0; |
219 | } | 219 | } |
220 | debug("PXM50: %d\n", factory_dat.pxm50); | 220 | debug("PXM50: %d\n", factory_dat.pxm50); |
221 | #if defined(CONFIG_VIDEO) | 221 | #if defined(CONFIG_VIDEO) |
222 | if (0 <= get_factory_record_val(cp, size, (uchar *)"DISP1", | 222 | if (0 <= get_factory_record_val(cp, size, (uchar *)"DISP1", |
223 | (uchar *)"name", factory_dat.disp_name, | 223 | (uchar *)"name", factory_dat.disp_name, |
224 | MAX_STRING_LENGTH)) { | 224 | MAX_STRING_LENGTH)) { |
225 | debug("display name: %s\n", factory_dat.disp_name); | 225 | debug("display name: %s\n", factory_dat.disp_name); |
226 | } | 226 | } |
227 | 227 | ||
228 | #endif | 228 | #endif |
229 | return 0; | 229 | return 0; |
230 | 230 | ||
231 | err: | 231 | err: |
232 | printf("Could not read the EEPROM; something fundamentally wrong on the I2C bus.\n"); | 232 | printf("Could not read the EEPROM; something fundamentally wrong on the I2C bus.\n"); |
233 | return 1; | 233 | return 1; |
234 | } | 234 | } |
235 | 235 | ||
236 | static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; | 236 | static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; |
237 | 237 | ||
238 | static int factoryset_mac_setenv(void) | 238 | static int factoryset_mac_setenv(void) |
239 | { | 239 | { |
240 | uint8_t mac_addr[6]; | 240 | uint8_t mac_addr[6]; |
241 | 241 | ||
242 | debug("FactorySet: Set mac address\n"); | 242 | debug("FactorySet: Set mac address\n"); |
243 | if (is_valid_ether_addr(factory_dat.mac)) { | 243 | if (is_valid_ether_addr(factory_dat.mac)) { |
244 | memcpy(mac_addr, factory_dat.mac, 6); | 244 | memcpy(mac_addr, factory_dat.mac, 6); |
245 | } else { | 245 | } else { |
246 | uint32_t mac_hi, mac_lo; | 246 | uint32_t mac_hi, mac_lo; |
247 | 247 | ||
248 | debug("Warning: FactorySet: <ethaddr> not set. Fallback to E-fuse\n"); | 248 | debug("Warning: FactorySet: <ethaddr> not set. Fallback to E-fuse\n"); |
249 | mac_lo = readl(&cdev->macid0l); | 249 | mac_lo = readl(&cdev->macid0l); |
250 | mac_hi = readl(&cdev->macid0h); | 250 | mac_hi = readl(&cdev->macid0h); |
251 | 251 | ||
252 | mac_addr[0] = mac_hi & 0xFF; | 252 | mac_addr[0] = mac_hi & 0xFF; |
253 | mac_addr[1] = (mac_hi & 0xFF00) >> 8; | 253 | mac_addr[1] = (mac_hi & 0xFF00) >> 8; |
254 | mac_addr[2] = (mac_hi & 0xFF0000) >> 16; | 254 | mac_addr[2] = (mac_hi & 0xFF0000) >> 16; |
255 | mac_addr[3] = (mac_hi & 0xFF000000) >> 24; | 255 | mac_addr[3] = (mac_hi & 0xFF000000) >> 24; |
256 | mac_addr[4] = mac_lo & 0xFF; | 256 | mac_addr[4] = mac_lo & 0xFF; |
257 | mac_addr[5] = (mac_lo & 0xFF00) >> 8; | 257 | mac_addr[5] = (mac_lo & 0xFF00) >> 8; |
258 | if (!is_valid_ether_addr(mac_addr)) { | 258 | if (!is_valid_ether_addr(mac_addr)) { |
259 | printf("Warning: ethaddr not set by FactorySet or E-fuse. Set <ethaddr> variable to overcome this.\n"); | 259 | printf("Warning: ethaddr not set by FactorySet or E-fuse. Set <ethaddr> variable to overcome this.\n"); |
260 | return -1; | 260 | return -1; |
261 | } | 261 | } |
262 | } | 262 | } |
263 | 263 | ||
264 | eth_setenv_enetaddr("ethaddr", mac_addr); | 264 | eth_setenv_enetaddr("ethaddr", mac_addr); |
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
268 | int factoryset_setenv(void) | 268 | int factoryset_setenv(void) |
269 | { | 269 | { |
270 | int ret = 0; | 270 | int ret = 0; |
271 | 271 | ||
272 | if (factoryset_mac_setenv() < 0) | 272 | if (factoryset_mac_setenv() < 0) |
273 | ret = -1; | 273 | ret = -1; |
274 | 274 | ||
275 | return ret; | 275 | return ret; |
276 | } | 276 | } |
277 | 277 | ||
278 | int g_dnl_bind_fixup(struct usb_device_descriptor *dev) | 278 | int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) |
279 | { | 279 | { |
280 | put_unaligned(factory_dat.usb_vendor_id, &dev->idVendor); | 280 | put_unaligned(factory_dat.usb_vendor_id, &dev->idVendor); |
281 | put_unaligned(factory_dat.usb_product_id, &dev->idProduct); | 281 | put_unaligned(factory_dat.usb_product_id, &dev->idProduct); |
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | #endif /* defined(CONFIG_SPL_BUILD) */ | 284 | #endif /* defined(CONFIG_SPL_BUILD) */ |
285 | 285 |
drivers/usb/gadget/g_dnl.c
1 | /* | 1 | /* |
2 | * g_dnl.c -- USB Downloader Gadget | 2 | * g_dnl.c -- USB Downloader Gadget |
3 | * | 3 | * |
4 | * Copyright (C) 2012 Samsung Electronics | 4 | * Copyright (C) 2012 Samsung Electronics |
5 | * Lukasz Majewski <l.majewski@samsung.com> | 5 | * Lukasz Majewski <l.majewski@samsung.com> |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: GPL-2.0+ | 7 | * SPDX-License-Identifier: GPL-2.0+ |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <common.h> | 10 | #include <common.h> |
11 | #include <malloc.h> | 11 | #include <malloc.h> |
12 | 12 | ||
13 | #include <mmc.h> | 13 | #include <mmc.h> |
14 | #include <part.h> | 14 | #include <part.h> |
15 | 15 | ||
16 | #include <g_dnl.h> | 16 | #include <g_dnl.h> |
17 | #include <usb_mass_storage.h> | 17 | #include <usb_mass_storage.h> |
18 | #include <dfu.h> | 18 | #include <dfu.h> |
19 | 19 | ||
20 | #include "gadget_chips.h" | 20 | #include "gadget_chips.h" |
21 | #include "composite.c" | 21 | #include "composite.c" |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * One needs to define the following: | 24 | * One needs to define the following: |
25 | * CONFIG_G_DNL_VENDOR_NUM | 25 | * CONFIG_G_DNL_VENDOR_NUM |
26 | * CONFIG_G_DNL_PRODUCT_NUM | 26 | * CONFIG_G_DNL_PRODUCT_NUM |
27 | * CONFIG_G_DNL_MANUFACTURER | 27 | * CONFIG_G_DNL_MANUFACTURER |
28 | * at e.g. ./include/configs/<board>.h | 28 | * at e.g. ./include/configs/<board>.h |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #define STRING_MANUFACTURER 25 | 31 | #define STRING_MANUFACTURER 25 |
32 | #define STRING_PRODUCT 2 | 32 | #define STRING_PRODUCT 2 |
33 | /* Index of String Descriptor describing this configuration */ | 33 | /* Index of String Descriptor describing this configuration */ |
34 | #define STRING_USBDOWN 2 | 34 | #define STRING_USBDOWN 2 |
35 | /* Number of supported configurations */ | 35 | /* Number of supported configurations */ |
36 | #define CONFIGURATION_NUMBER 1 | 36 | #define CONFIGURATION_NUMBER 1 |
37 | 37 | ||
38 | #define DRIVER_VERSION "usb_dnl 2.0" | 38 | #define DRIVER_VERSION "usb_dnl 2.0" |
39 | 39 | ||
40 | static const char shortname[] = "usb_dnl_"; | 40 | static const char shortname[] = "usb_dnl_"; |
41 | static const char product[] = "USB download gadget"; | 41 | static const char product[] = "USB download gadget"; |
42 | static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER; | 42 | static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER; |
43 | 43 | ||
44 | static struct usb_device_descriptor device_desc = { | 44 | static struct usb_device_descriptor device_desc = { |
45 | .bLength = sizeof device_desc, | 45 | .bLength = sizeof device_desc, |
46 | .bDescriptorType = USB_DT_DEVICE, | 46 | .bDescriptorType = USB_DT_DEVICE, |
47 | 47 | ||
48 | .bcdUSB = __constant_cpu_to_le16(0x0200), | 48 | .bcdUSB = __constant_cpu_to_le16(0x0200), |
49 | .bDeviceClass = USB_CLASS_COMM, | 49 | .bDeviceClass = USB_CLASS_COMM, |
50 | .bDeviceSubClass = 0x02, /*0x02:CDC-modem , 0x00:CDC-serial*/ | 50 | .bDeviceSubClass = 0x02, /*0x02:CDC-modem , 0x00:CDC-serial*/ |
51 | 51 | ||
52 | .idVendor = __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM), | 52 | .idVendor = __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM), |
53 | .idProduct = __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM), | 53 | .idProduct = __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM), |
54 | .iProduct = STRING_PRODUCT, | 54 | .iProduct = STRING_PRODUCT, |
55 | .bNumConfigurations = 1, | 55 | .bNumConfigurations = 1, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * static strings, in UTF-8 | 59 | * static strings, in UTF-8 |
60 | * IDs for those strings are assigned dynamically at g_dnl_bind() | 60 | * IDs for those strings are assigned dynamically at g_dnl_bind() |
61 | */ | 61 | */ |
62 | static struct usb_string g_dnl_string_defs[] = { | 62 | static struct usb_string g_dnl_string_defs[] = { |
63 | {.s = manufacturer}, | 63 | {.s = manufacturer}, |
64 | {.s = product}, | 64 | {.s = product}, |
65 | { } /* end of list */ | 65 | { } /* end of list */ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static struct usb_gadget_strings g_dnl_string_tab = { | 68 | static struct usb_gadget_strings g_dnl_string_tab = { |
69 | .language = 0x0409, /* en-us */ | 69 | .language = 0x0409, /* en-us */ |
70 | .strings = g_dnl_string_defs, | 70 | .strings = g_dnl_string_defs, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static struct usb_gadget_strings *g_dnl_composite_strings[] = { | 73 | static struct usb_gadget_strings *g_dnl_composite_strings[] = { |
74 | &g_dnl_string_tab, | 74 | &g_dnl_string_tab, |
75 | NULL, | 75 | NULL, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static int g_dnl_unbind(struct usb_composite_dev *cdev) | 78 | static int g_dnl_unbind(struct usb_composite_dev *cdev) |
79 | { | 79 | { |
80 | struct usb_gadget *gadget = cdev->gadget; | 80 | struct usb_gadget *gadget = cdev->gadget; |
81 | 81 | ||
82 | free(cdev->config); | 82 | free(cdev->config); |
83 | cdev->config = NULL; | 83 | cdev->config = NULL; |
84 | debug("%s: calling usb_gadget_disconnect for " | 84 | debug("%s: calling usb_gadget_disconnect for " |
85 | "controller '%s'\n", shortname, gadget->name); | 85 | "controller '%s'\n", shortname, gadget->name); |
86 | usb_gadget_disconnect(gadget); | 86 | usb_gadget_disconnect(gadget); |
87 | 87 | ||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | static int g_dnl_do_config(struct usb_configuration *c) | 91 | static int g_dnl_do_config(struct usb_configuration *c) |
92 | { | 92 | { |
93 | const char *s = c->cdev->driver->name; | 93 | const char *s = c->cdev->driver->name; |
94 | int ret = -1; | 94 | int ret = -1; |
95 | 95 | ||
96 | debug("%s: configuration: 0x%p composite dev: 0x%p\n", | 96 | debug("%s: configuration: 0x%p composite dev: 0x%p\n", |
97 | __func__, c, c->cdev); | 97 | __func__, c, c->cdev); |
98 | 98 | ||
99 | printf("GADGET DRIVER: %s\n", s); | 99 | printf("GADGET DRIVER: %s\n", s); |
100 | if (!strcmp(s, "usb_dnl_dfu")) | 100 | if (!strcmp(s, "usb_dnl_dfu")) |
101 | ret = dfu_add(c); | 101 | ret = dfu_add(c); |
102 | else if (!strcmp(s, "usb_dnl_ums")) | 102 | else if (!strcmp(s, "usb_dnl_ums")) |
103 | ret = fsg_add(c); | 103 | ret = fsg_add(c); |
104 | 104 | ||
105 | return ret; | 105 | return ret; |
106 | } | 106 | } |
107 | 107 | ||
108 | static int g_dnl_config_register(struct usb_composite_dev *cdev) | 108 | static int g_dnl_config_register(struct usb_composite_dev *cdev) |
109 | { | 109 | { |
110 | struct usb_configuration *config; | 110 | struct usb_configuration *config; |
111 | const char *name = "usb_dnload"; | 111 | const char *name = "usb_dnload"; |
112 | 112 | ||
113 | config = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*config)); | 113 | config = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*config)); |
114 | if (!config) | 114 | if (!config) |
115 | return -ENOMEM; | 115 | return -ENOMEM; |
116 | 116 | ||
117 | memset(config, 0, sizeof(*config)); | 117 | memset(config, 0, sizeof(*config)); |
118 | 118 | ||
119 | config->label = name; | 119 | config->label = name; |
120 | config->bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER; | 120 | config->bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER; |
121 | config->bConfigurationValue = CONFIGURATION_NUMBER; | 121 | config->bConfigurationValue = CONFIGURATION_NUMBER; |
122 | config->iConfiguration = STRING_USBDOWN; | 122 | config->iConfiguration = STRING_USBDOWN; |
123 | config->bind = g_dnl_do_config; | 123 | config->bind = g_dnl_do_config; |
124 | 124 | ||
125 | return usb_add_config(cdev, config); | 125 | return usb_add_config(cdev, config); |
126 | } | 126 | } |
127 | 127 | ||
128 | __weak | 128 | __weak |
129 | int g_dnl_bind_fixup(struct usb_device_descriptor *dev) | 129 | int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) |
130 | { | 130 | { |
131 | return 0; | 131 | return 0; |
132 | } | 132 | } |
133 | 133 | ||
134 | static int g_dnl_bind(struct usb_composite_dev *cdev) | 134 | static int g_dnl_bind(struct usb_composite_dev *cdev) |
135 | { | 135 | { |
136 | struct usb_gadget *gadget = cdev->gadget; | 136 | struct usb_gadget *gadget = cdev->gadget; |
137 | int id, ret; | 137 | int id, ret; |
138 | int gcnum; | 138 | int gcnum; |
139 | 139 | ||
140 | debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev); | 140 | debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev); |
141 | 141 | ||
142 | id = usb_string_id(cdev); | 142 | id = usb_string_id(cdev); |
143 | 143 | ||
144 | if (id < 0) | 144 | if (id < 0) |
145 | return id; | 145 | return id; |
146 | g_dnl_string_defs[0].id = id; | 146 | g_dnl_string_defs[0].id = id; |
147 | device_desc.iManufacturer = id; | 147 | device_desc.iManufacturer = id; |
148 | 148 | ||
149 | id = usb_string_id(cdev); | 149 | id = usb_string_id(cdev); |
150 | if (id < 0) | 150 | if (id < 0) |
151 | return id; | 151 | return id; |
152 | 152 | ||
153 | g_dnl_string_defs[1].id = id; | 153 | g_dnl_string_defs[1].id = id; |
154 | device_desc.iProduct = id; | 154 | device_desc.iProduct = id; |
155 | 155 | ||
156 | g_dnl_bind_fixup(&device_desc); | 156 | g_dnl_bind_fixup(&device_desc, cdev->driver->name); |
157 | ret = g_dnl_config_register(cdev); | 157 | ret = g_dnl_config_register(cdev); |
158 | if (ret) | 158 | if (ret) |
159 | goto error; | 159 | goto error; |
160 | 160 | ||
161 | gcnum = usb_gadget_controller_number(gadget); | 161 | gcnum = usb_gadget_controller_number(gadget); |
162 | 162 | ||
163 | debug("gcnum: %d\n", gcnum); | 163 | debug("gcnum: %d\n", gcnum); |
164 | if (gcnum >= 0) | 164 | if (gcnum >= 0) |
165 | device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); | 165 | device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); |
166 | else { | 166 | else { |
167 | debug("%s: controller '%s' not recognized\n", | 167 | debug("%s: controller '%s' not recognized\n", |
168 | shortname, gadget->name); | 168 | shortname, gadget->name); |
169 | device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); | 169 | device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); |
170 | } | 170 | } |
171 | 171 | ||
172 | debug("%s: calling usb_gadget_connect for " | 172 | debug("%s: calling usb_gadget_connect for " |
173 | "controller '%s'\n", shortname, gadget->name); | 173 | "controller '%s'\n", shortname, gadget->name); |
174 | usb_gadget_connect(gadget); | 174 | usb_gadget_connect(gadget); |
175 | 175 | ||
176 | return 0; | 176 | return 0; |
177 | 177 | ||
178 | error: | 178 | error: |
179 | g_dnl_unbind(cdev); | 179 | g_dnl_unbind(cdev); |
180 | return -ENOMEM; | 180 | return -ENOMEM; |
181 | } | 181 | } |
182 | 182 | ||
183 | static struct usb_composite_driver g_dnl_driver = { | 183 | static struct usb_composite_driver g_dnl_driver = { |
184 | .name = NULL, | 184 | .name = NULL, |
185 | .dev = &device_desc, | 185 | .dev = &device_desc, |
186 | .strings = g_dnl_composite_strings, | 186 | .strings = g_dnl_composite_strings, |
187 | 187 | ||
188 | .bind = g_dnl_bind, | 188 | .bind = g_dnl_bind, |
189 | .unbind = g_dnl_unbind, | 189 | .unbind = g_dnl_unbind, |
190 | }; | 190 | }; |
191 | 191 | ||
192 | int g_dnl_register(const char *type) | 192 | int g_dnl_register(const char *type) |
193 | { | 193 | { |
194 | /* We only allow "dfu" atm, so 3 should be enough */ | 194 | /* We only allow "dfu" atm, so 3 should be enough */ |
195 | static char name[sizeof(shortname) + 3]; | 195 | static char name[sizeof(shortname) + 3]; |
196 | int ret; | 196 | int ret; |
197 | 197 | ||
198 | if (!strcmp(type, "dfu")) { | 198 | if (!strcmp(type, "dfu")) { |
199 | strcpy(name, shortname); | 199 | strcpy(name, shortname); |
200 | strcat(name, type); | 200 | strcat(name, type); |
201 | } else if (!strcmp(type, "ums")) { | 201 | } else if (!strcmp(type, "ums")) { |
202 | strcpy(name, shortname); | 202 | strcpy(name, shortname); |
203 | strcat(name, type); | 203 | strcat(name, type); |
204 | } else { | 204 | } else { |
205 | printf("%s: unknown command: %s\n", __func__, type); | 205 | printf("%s: unknown command: %s\n", __func__, type); |
206 | return -EINVAL; | 206 | return -EINVAL; |
207 | } | 207 | } |
208 | 208 | ||
209 | g_dnl_driver.name = name; | 209 | g_dnl_driver.name = name; |
210 | 210 | ||
211 | debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name); | 211 | debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name); |
212 | ret = usb_composite_register(&g_dnl_driver); | 212 | ret = usb_composite_register(&g_dnl_driver); |
213 | 213 | ||
214 | if (ret) { | 214 | if (ret) { |
215 | printf("%s: failed!, error: %d\n", __func__, ret); | 215 | printf("%s: failed!, error: %d\n", __func__, ret); |
216 | return ret; | 216 | return ret; |
217 | } | 217 | } |
218 | 218 | ||
219 | return 0; | 219 | return 0; |
220 | } | 220 | } |
221 | 221 | ||
222 | void g_dnl_unregister(void) | 222 | void g_dnl_unregister(void) |
223 | { | 223 | { |
224 | usb_composite_unregister(&g_dnl_driver); | 224 | usb_composite_unregister(&g_dnl_driver); |
225 | } | 225 | } |
226 | 226 |
include/g_dnl.h
1 | /* | 1 | /* |
2 | * Copyright (C) 2012 Samsung Electronics | 2 | * Copyright (C) 2012 Samsung Electronics |
3 | * Lukasz Majewski <l.majewski@samsung.com> | 3 | * Lukasz Majewski <l.majewski@samsung.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef __G_DOWNLOAD_H_ | 8 | #ifndef __G_DOWNLOAD_H_ |
9 | #define __G_DOWNLOAD_H_ | 9 | #define __G_DOWNLOAD_H_ |
10 | 10 | ||
11 | #include <linux/usb/ch9.h> | 11 | #include <linux/usb/ch9.h> |
12 | #include <linux/usb/gadget.h> | 12 | #include <linux/usb/gadget.h> |
13 | int g_dnl_bind_fixup(struct usb_device_descriptor *); | 13 | int g_dnl_bind_fixup(struct usb_device_descriptor *, const char *); |
14 | int g_dnl_register(const char *s); | 14 | int g_dnl_register(const char *s); |
15 | void g_dnl_unregister(void); | 15 | void g_dnl_unregister(void); |
16 | 16 | ||
17 | #endif /* __G_DOWNLOAD_H_ */ | 17 | #endif /* __G_DOWNLOAD_H_ */ |
18 | 18 |