diff options
author | Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 2013-05-23 03:22:06 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-06-10 10:12:18 -0400 |
commit | 40d133d7f542616cf9538508a372306e626a16e9 (patch) | |
tree | d20ea74f77adc27ab8e26bf4edfb5c969951edaf /drivers | |
parent | bcd4a1c40bee885e5266ca53de05d985a5518d7a (diff) |
usb: gadget: f_ncm: convert to new function interface with backward compatibility
Converting ncm to the new function interface requires converting
the USB ncm's function code and its users.
This patch converts the f_ncm.c to the new function interface.
The file is now compiled into a separate usb_f_ncm.ko module.
The old function interface is provided by means of a preprocessor
conditional directives. After all users are converted, the old interface
can be removed.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/Kconfig | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/f_ncm.c | 196 | ||||
-rw-r--r-- | drivers/usb/gadget/ncm.c | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/u_ncm.h | 27 |
5 files changed, 194 insertions, 35 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5345b6895220..127292ffb4d9 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -511,6 +511,9 @@ config USB_F_SERIAL | |||
511 | config USB_F_OBEX | 511 | config USB_F_OBEX |
512 | tristate | 512 | tristate |
513 | 513 | ||
514 | config USB_F_NCM | ||
515 | tristate | ||
516 | |||
514 | choice | 517 | choice |
515 | tristate "USB Gadget Drivers" | 518 | tristate "USB Gadget Drivers" |
516 | default USB_ETH | 519 | default USB_ETH |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 7a0463ef3684..34b117eec36e 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -48,6 +48,8 @@ obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o | |||
48 | obj-$(CONFIG_USB_U_ETHER) += u_ether.o | 48 | obj-$(CONFIG_USB_U_ETHER) += u_ether.o |
49 | u_rndis-y := rndis.o | 49 | u_rndis-y := rndis.o |
50 | obj-$(CONFIG_USB_U_RNDIS) += u_rndis.o | 50 | obj-$(CONFIG_USB_U_RNDIS) += u_rndis.o |
51 | usb_f_ncm-y := f_ncm.o | ||
52 | obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o | ||
51 | 53 | ||
52 | # | 54 | # |
53 | # USB gadget drivers | 55 | # USB gadget drivers |
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index ee19bc8d0040..722ca1b0dda0 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | ||
19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
20 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
21 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
@@ -23,6 +24,7 @@ | |||
23 | #include <linux/usb/cdc.h> | 24 | #include <linux/usb/cdc.h> |
24 | 25 | ||
25 | #include "u_ether.h" | 26 | #include "u_ether.h" |
27 | #include "u_ncm.h" | ||
26 | 28 | ||
27 | /* | 29 | /* |
28 | * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link. | 30 | * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link. |
@@ -125,7 +127,7 @@ static struct usb_cdc_ncm_ntb_parameters ntb_parameters = { | |||
125 | #define NCM_STATUS_INTERVAL_MS 32 | 127 | #define NCM_STATUS_INTERVAL_MS 32 |
126 | #define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */ | 128 | #define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */ |
127 | 129 | ||
128 | static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = { | 130 | static struct usb_interface_assoc_descriptor ncm_iad_desc = { |
129 | .bLength = sizeof ncm_iad_desc, | 131 | .bLength = sizeof ncm_iad_desc, |
130 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, | 132 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
131 | 133 | ||
@@ -139,7 +141,7 @@ static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = { | |||
139 | 141 | ||
140 | /* interface descriptor: */ | 142 | /* interface descriptor: */ |
141 | 143 | ||
142 | static struct usb_interface_descriptor ncm_control_intf __initdata = { | 144 | static struct usb_interface_descriptor ncm_control_intf = { |
143 | .bLength = sizeof ncm_control_intf, | 145 | .bLength = sizeof ncm_control_intf, |
144 | .bDescriptorType = USB_DT_INTERFACE, | 146 | .bDescriptorType = USB_DT_INTERFACE, |
145 | 147 | ||
@@ -151,7 +153,7 @@ static struct usb_interface_descriptor ncm_control_intf __initdata = { | |||
151 | /* .iInterface = DYNAMIC */ | 153 | /* .iInterface = DYNAMIC */ |
152 | }; | 154 | }; |
153 | 155 | ||
154 | static struct usb_cdc_header_desc ncm_header_desc __initdata = { | 156 | static struct usb_cdc_header_desc ncm_header_desc = { |
155 | .bLength = sizeof ncm_header_desc, | 157 | .bLength = sizeof ncm_header_desc, |
156 | .bDescriptorType = USB_DT_CS_INTERFACE, | 158 | .bDescriptorType = USB_DT_CS_INTERFACE, |
157 | .bDescriptorSubType = USB_CDC_HEADER_TYPE, | 159 | .bDescriptorSubType = USB_CDC_HEADER_TYPE, |
@@ -159,7 +161,7 @@ static struct usb_cdc_header_desc ncm_header_desc __initdata = { | |||
159 | .bcdCDC = cpu_to_le16(0x0110), | 161 | .bcdCDC = cpu_to_le16(0x0110), |
160 | }; | 162 | }; |
161 | 163 | ||
162 | static struct usb_cdc_union_desc ncm_union_desc __initdata = { | 164 | static struct usb_cdc_union_desc ncm_union_desc = { |
163 | .bLength = sizeof(ncm_union_desc), | 165 | .bLength = sizeof(ncm_union_desc), |
164 | .bDescriptorType = USB_DT_CS_INTERFACE, | 166 | .bDescriptorType = USB_DT_CS_INTERFACE, |
165 | .bDescriptorSubType = USB_CDC_UNION_TYPE, | 167 | .bDescriptorSubType = USB_CDC_UNION_TYPE, |
@@ -167,7 +169,7 @@ static struct usb_cdc_union_desc ncm_union_desc __initdata = { | |||
167 | /* .bSlaveInterface0 = DYNAMIC */ | 169 | /* .bSlaveInterface0 = DYNAMIC */ |
168 | }; | 170 | }; |
169 | 171 | ||
170 | static struct usb_cdc_ether_desc ecm_desc __initdata = { | 172 | static struct usb_cdc_ether_desc ecm_desc = { |
171 | .bLength = sizeof ecm_desc, | 173 | .bLength = sizeof ecm_desc, |
172 | .bDescriptorType = USB_DT_CS_INTERFACE, | 174 | .bDescriptorType = USB_DT_CS_INTERFACE, |
173 | .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, | 175 | .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, |
@@ -182,7 +184,7 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = { | |||
182 | 184 | ||
183 | #define NCAPS (USB_CDC_NCM_NCAP_ETH_FILTER | USB_CDC_NCM_NCAP_CRC_MODE) | 185 | #define NCAPS (USB_CDC_NCM_NCAP_ETH_FILTER | USB_CDC_NCM_NCAP_CRC_MODE) |
184 | 186 | ||
185 | static struct usb_cdc_ncm_desc ncm_desc __initdata = { | 187 | static struct usb_cdc_ncm_desc ncm_desc = { |
186 | .bLength = sizeof ncm_desc, | 188 | .bLength = sizeof ncm_desc, |
187 | .bDescriptorType = USB_DT_CS_INTERFACE, | 189 | .bDescriptorType = USB_DT_CS_INTERFACE, |
188 | .bDescriptorSubType = USB_CDC_NCM_TYPE, | 190 | .bDescriptorSubType = USB_CDC_NCM_TYPE, |
@@ -194,7 +196,7 @@ static struct usb_cdc_ncm_desc ncm_desc __initdata = { | |||
194 | 196 | ||
195 | /* the default data interface has no endpoints ... */ | 197 | /* the default data interface has no endpoints ... */ |
196 | 198 | ||
197 | static struct usb_interface_descriptor ncm_data_nop_intf __initdata = { | 199 | static struct usb_interface_descriptor ncm_data_nop_intf = { |
198 | .bLength = sizeof ncm_data_nop_intf, | 200 | .bLength = sizeof ncm_data_nop_intf, |
199 | .bDescriptorType = USB_DT_INTERFACE, | 201 | .bDescriptorType = USB_DT_INTERFACE, |
200 | 202 | ||
@@ -209,7 +211,7 @@ static struct usb_interface_descriptor ncm_data_nop_intf __initdata = { | |||
209 | 211 | ||
210 | /* ... but the "real" data interface has two bulk endpoints */ | 212 | /* ... but the "real" data interface has two bulk endpoints */ |
211 | 213 | ||
212 | static struct usb_interface_descriptor ncm_data_intf __initdata = { | 214 | static struct usb_interface_descriptor ncm_data_intf = { |
213 | .bLength = sizeof ncm_data_intf, | 215 | .bLength = sizeof ncm_data_intf, |
214 | .bDescriptorType = USB_DT_INTERFACE, | 216 | .bDescriptorType = USB_DT_INTERFACE, |
215 | 217 | ||
@@ -224,7 +226,7 @@ static struct usb_interface_descriptor ncm_data_intf __initdata = { | |||
224 | 226 | ||
225 | /* full speed support: */ | 227 | /* full speed support: */ |
226 | 228 | ||
227 | static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = { | 229 | static struct usb_endpoint_descriptor fs_ncm_notify_desc = { |
228 | .bLength = USB_DT_ENDPOINT_SIZE, | 230 | .bLength = USB_DT_ENDPOINT_SIZE, |
229 | .bDescriptorType = USB_DT_ENDPOINT, | 231 | .bDescriptorType = USB_DT_ENDPOINT, |
230 | 232 | ||
@@ -234,7 +236,7 @@ static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = { | |||
234 | .bInterval = NCM_STATUS_INTERVAL_MS, | 236 | .bInterval = NCM_STATUS_INTERVAL_MS, |
235 | }; | 237 | }; |
236 | 238 | ||
237 | static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = { | 239 | static struct usb_endpoint_descriptor fs_ncm_in_desc = { |
238 | .bLength = USB_DT_ENDPOINT_SIZE, | 240 | .bLength = USB_DT_ENDPOINT_SIZE, |
239 | .bDescriptorType = USB_DT_ENDPOINT, | 241 | .bDescriptorType = USB_DT_ENDPOINT, |
240 | 242 | ||
@@ -242,7 +244,7 @@ static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = { | |||
242 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 244 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
243 | }; | 245 | }; |
244 | 246 | ||
245 | static struct usb_endpoint_descriptor fs_ncm_out_desc __initdata = { | 247 | static struct usb_endpoint_descriptor fs_ncm_out_desc = { |
246 | .bLength = USB_DT_ENDPOINT_SIZE, | 248 | .bLength = USB_DT_ENDPOINT_SIZE, |
247 | .bDescriptorType = USB_DT_ENDPOINT, | 249 | .bDescriptorType = USB_DT_ENDPOINT, |
248 | 250 | ||
@@ -250,7 +252,7 @@ static struct usb_endpoint_descriptor fs_ncm_out_desc __initdata = { | |||
250 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 252 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
251 | }; | 253 | }; |
252 | 254 | ||
253 | static struct usb_descriptor_header *ncm_fs_function[] __initdata = { | 255 | static struct usb_descriptor_header *ncm_fs_function[] = { |
254 | (struct usb_descriptor_header *) &ncm_iad_desc, | 256 | (struct usb_descriptor_header *) &ncm_iad_desc, |
255 | /* CDC NCM control descriptors */ | 257 | /* CDC NCM control descriptors */ |
256 | (struct usb_descriptor_header *) &ncm_control_intf, | 258 | (struct usb_descriptor_header *) &ncm_control_intf, |
@@ -269,7 +271,7 @@ static struct usb_descriptor_header *ncm_fs_function[] __initdata = { | |||
269 | 271 | ||
270 | /* high speed support: */ | 272 | /* high speed support: */ |
271 | 273 | ||
272 | static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = { | 274 | static struct usb_endpoint_descriptor hs_ncm_notify_desc = { |
273 | .bLength = USB_DT_ENDPOINT_SIZE, | 275 | .bLength = USB_DT_ENDPOINT_SIZE, |
274 | .bDescriptorType = USB_DT_ENDPOINT, | 276 | .bDescriptorType = USB_DT_ENDPOINT, |
275 | 277 | ||
@@ -278,7 +280,7 @@ static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = { | |||
278 | .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), | 280 | .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), |
279 | .bInterval = USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS), | 281 | .bInterval = USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS), |
280 | }; | 282 | }; |
281 | static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = { | 283 | static struct usb_endpoint_descriptor hs_ncm_in_desc = { |
282 | .bLength = USB_DT_ENDPOINT_SIZE, | 284 | .bLength = USB_DT_ENDPOINT_SIZE, |
283 | .bDescriptorType = USB_DT_ENDPOINT, | 285 | .bDescriptorType = USB_DT_ENDPOINT, |
284 | 286 | ||
@@ -287,7 +289,7 @@ static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = { | |||
287 | .wMaxPacketSize = cpu_to_le16(512), | 289 | .wMaxPacketSize = cpu_to_le16(512), |
288 | }; | 290 | }; |
289 | 291 | ||
290 | static struct usb_endpoint_descriptor hs_ncm_out_desc __initdata = { | 292 | static struct usb_endpoint_descriptor hs_ncm_out_desc = { |
291 | .bLength = USB_DT_ENDPOINT_SIZE, | 293 | .bLength = USB_DT_ENDPOINT_SIZE, |
292 | .bDescriptorType = USB_DT_ENDPOINT, | 294 | .bDescriptorType = USB_DT_ENDPOINT, |
293 | 295 | ||
@@ -296,7 +298,7 @@ static struct usb_endpoint_descriptor hs_ncm_out_desc __initdata = { | |||
296 | .wMaxPacketSize = cpu_to_le16(512), | 298 | .wMaxPacketSize = cpu_to_le16(512), |
297 | }; | 299 | }; |
298 | 300 | ||
299 | static struct usb_descriptor_header *ncm_hs_function[] __initdata = { | 301 | static struct usb_descriptor_header *ncm_hs_function[] = { |
300 | (struct usb_descriptor_header *) &ncm_iad_desc, | 302 | (struct usb_descriptor_header *) &ncm_iad_desc, |
301 | /* CDC NCM control descriptors */ | 303 | /* CDC NCM control descriptors */ |
302 | (struct usb_descriptor_header *) &ncm_control_intf, | 304 | (struct usb_descriptor_header *) &ncm_control_intf, |
@@ -1152,14 +1154,50 @@ static void ncm_close(struct gether *geth) | |||
1152 | 1154 | ||
1153 | /* ethernet function driver setup/binding */ | 1155 | /* ethernet function driver setup/binding */ |
1154 | 1156 | ||
1155 | static int __init | 1157 | static int ncm_bind(struct usb_configuration *c, struct usb_function *f) |
1156 | ncm_bind(struct usb_configuration *c, struct usb_function *f) | ||
1157 | { | 1158 | { |
1158 | struct usb_composite_dev *cdev = c->cdev; | 1159 | struct usb_composite_dev *cdev = c->cdev; |
1159 | struct f_ncm *ncm = func_to_ncm(f); | 1160 | struct f_ncm *ncm = func_to_ncm(f); |
1160 | int status; | 1161 | int status; |
1161 | struct usb_ep *ep; | 1162 | struct usb_ep *ep; |
1162 | 1163 | ||
1164 | #ifndef USB_FNCM_INCLUDED | ||
1165 | struct f_ncm_opts *ncm_opts; | ||
1166 | |||
1167 | if (!can_support_ecm(cdev->gadget)) | ||
1168 | return -EINVAL; | ||
1169 | |||
1170 | ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst); | ||
1171 | /* | ||
1172 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
1173 | * configurations are bound in sequence with list_for_each_entry, | ||
1174 | * in each configuration its functions are bound in sequence | ||
1175 | * with list_for_each_entry, so we assume no race condition | ||
1176 | * with regard to ncm_opts->bound access | ||
1177 | */ | ||
1178 | if (!ncm_opts->bound) { | ||
1179 | gether_set_gadget(ncm_opts->net, cdev->gadget); | ||
1180 | status = gether_register_netdev(ncm_opts->net); | ||
1181 | if (status) | ||
1182 | return status; | ||
1183 | ncm_opts->bound = true; | ||
1184 | } | ||
1185 | #endif | ||
1186 | if (ncm_string_defs[0].id == 0) { | ||
1187 | status = usb_string_ids_tab(c->cdev, ncm_string_defs); | ||
1188 | if (status < 0) | ||
1189 | return status; | ||
1190 | ncm_control_intf.iInterface = | ||
1191 | ncm_string_defs[STRING_CTRL_IDX].id; | ||
1192 | |||
1193 | status = ncm_string_defs[STRING_DATA_IDX].id; | ||
1194 | ncm_data_nop_intf.iInterface = status; | ||
1195 | ncm_data_intf.iInterface = status; | ||
1196 | |||
1197 | ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id; | ||
1198 | ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id; | ||
1199 | } | ||
1200 | |||
1163 | /* allocate instance-specific interface IDs */ | 1201 | /* allocate instance-specific interface IDs */ |
1164 | status = usb_interface_id(c, f); | 1202 | status = usb_interface_id(c, f); |
1165 | if (status < 0) | 1203 | if (status < 0) |
@@ -1259,8 +1297,10 @@ fail: | |||
1259 | return status; | 1297 | return status; |
1260 | } | 1298 | } |
1261 | 1299 | ||
1300 | #ifdef USB_FNCM_INCLUDED | ||
1301 | |||
1262 | static void | 1302 | static void |
1263 | ncm_unbind(struct usb_configuration *c, struct usb_function *f) | 1303 | ncm_old_unbind(struct usb_configuration *c, struct usb_function *f) |
1264 | { | 1304 | { |
1265 | struct f_ncm *ncm = func_to_ncm(f); | 1305 | struct f_ncm *ncm = func_to_ncm(f); |
1266 | 1306 | ||
@@ -1296,21 +1336,6 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
1296 | if (!can_support_ecm(c->cdev->gadget) || !ethaddr) | 1336 | if (!can_support_ecm(c->cdev->gadget) || !ethaddr) |
1297 | return -EINVAL; | 1337 | return -EINVAL; |
1298 | 1338 | ||
1299 | if (ncm_string_defs[0].id == 0) { | ||
1300 | status = usb_string_ids_tab(c->cdev, ncm_string_defs); | ||
1301 | if (status < 0) | ||
1302 | return status; | ||
1303 | ncm_control_intf.iInterface = | ||
1304 | ncm_string_defs[STRING_CTRL_IDX].id; | ||
1305 | |||
1306 | status = ncm_string_defs[STRING_DATA_IDX].id; | ||
1307 | ncm_data_nop_intf.iInterface = status; | ||
1308 | ncm_data_intf.iInterface = status; | ||
1309 | |||
1310 | ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id; | ||
1311 | ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id; | ||
1312 | } | ||
1313 | |||
1314 | /* allocate and initialize one new instance */ | 1339 | /* allocate and initialize one new instance */ |
1315 | ncm = kzalloc(sizeof *ncm, GFP_KERNEL); | 1340 | ncm = kzalloc(sizeof *ncm, GFP_KERNEL); |
1316 | if (!ncm) | 1341 | if (!ncm) |
@@ -1329,7 +1354,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
1329 | ncm->port.func.strings = ncm_strings; | 1354 | ncm->port.func.strings = ncm_strings; |
1330 | /* descriptors are per-instance copies */ | 1355 | /* descriptors are per-instance copies */ |
1331 | ncm->port.func.bind = ncm_bind; | 1356 | ncm->port.func.bind = ncm_bind; |
1332 | ncm->port.func.unbind = ncm_unbind; | 1357 | ncm->port.func.unbind = ncm_old_unbind; |
1333 | ncm->port.func.set_alt = ncm_set_alt; | 1358 | ncm->port.func.set_alt = ncm_set_alt; |
1334 | ncm->port.func.get_alt = ncm_get_alt; | 1359 | ncm->port.func.get_alt = ncm_get_alt; |
1335 | ncm->port.func.setup = ncm_setup; | 1360 | ncm->port.func.setup = ncm_setup; |
@@ -1343,3 +1368,104 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
1343 | kfree(ncm); | 1368 | kfree(ncm); |
1344 | return status; | 1369 | return status; |
1345 | } | 1370 | } |
1371 | |||
1372 | #else | ||
1373 | |||
1374 | static void ncm_free_inst(struct usb_function_instance *f) | ||
1375 | { | ||
1376 | struct f_ncm_opts *opts; | ||
1377 | |||
1378 | opts = container_of(f, struct f_ncm_opts, func_inst); | ||
1379 | if (opts->bound) | ||
1380 | gether_cleanup(netdev_priv(opts->net)); | ||
1381 | else | ||
1382 | free_netdev(opts->net); | ||
1383 | kfree(opts); | ||
1384 | } | ||
1385 | |||
1386 | static struct usb_function_instance *ncm_alloc_inst(void) | ||
1387 | { | ||
1388 | struct f_ncm_opts *opts; | ||
1389 | |||
1390 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
1391 | if (!opts) | ||
1392 | return ERR_PTR(-ENOMEM); | ||
1393 | opts->func_inst.free_func_inst = ncm_free_inst; | ||
1394 | opts->net = gether_setup_default(); | ||
1395 | if (IS_ERR(opts->net)) | ||
1396 | return ERR_PTR(PTR_ERR(opts->net)); | ||
1397 | |||
1398 | return &opts->func_inst; | ||
1399 | } | ||
1400 | |||
1401 | static void ncm_free(struct usb_function *f) | ||
1402 | { | ||
1403 | struct f_ncm *ncm; | ||
1404 | |||
1405 | ncm = func_to_ncm(f); | ||
1406 | kfree(ncm); | ||
1407 | } | ||
1408 | |||
1409 | static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) | ||
1410 | { | ||
1411 | struct f_ncm *ncm = func_to_ncm(f); | ||
1412 | |||
1413 | DBG(c->cdev, "ncm unbind\n"); | ||
1414 | |||
1415 | ncm_string_defs[0].id = 0; | ||
1416 | usb_free_all_descriptors(f); | ||
1417 | |||
1418 | kfree(ncm->notify_req->buf); | ||
1419 | usb_ep_free_request(ncm->notify, ncm->notify_req); | ||
1420 | } | ||
1421 | |||
1422 | struct usb_function *ncm_alloc(struct usb_function_instance *fi) | ||
1423 | { | ||
1424 | struct f_ncm *ncm; | ||
1425 | struct f_ncm_opts *opts; | ||
1426 | int status; | ||
1427 | |||
1428 | /* allocate and initialize one new instance */ | ||
1429 | ncm = kzalloc(sizeof(*ncm), GFP_KERNEL); | ||
1430 | if (!ncm) | ||
1431 | return ERR_PTR(-ENOMEM); | ||
1432 | |||
1433 | opts = container_of(fi, struct f_ncm_opts, func_inst); | ||
1434 | |||
1435 | /* export host's Ethernet address in CDC format */ | ||
1436 | status = gether_get_host_addr_cdc(opts->net, ncm->ethaddr, | ||
1437 | sizeof(ncm->ethaddr)); | ||
1438 | if (status < 12) { /* strlen("01234567890a") */ | ||
1439 | kfree(ncm); | ||
1440 | return ERR_PTR(-EINVAL); | ||
1441 | } | ||
1442 | ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; | ||
1443 | |||
1444 | spin_lock_init(&ncm->lock); | ||
1445 | ncm_reset_values(ncm); | ||
1446 | ncm->port.ioport = netdev_priv(opts->net); | ||
1447 | ncm->port.is_fixed = true; | ||
1448 | |||
1449 | ncm->port.func.name = "cdc_network"; | ||
1450 | ncm->port.func.strings = ncm_strings; | ||
1451 | /* descriptors are per-instance copies */ | ||
1452 | ncm->port.func.bind = ncm_bind; | ||
1453 | ncm->port.func.unbind = ncm_unbind; | ||
1454 | ncm->port.func.set_alt = ncm_set_alt; | ||
1455 | ncm->port.func.get_alt = ncm_get_alt; | ||
1456 | ncm->port.func.setup = ncm_setup; | ||
1457 | ncm->port.func.disable = ncm_disable; | ||
1458 | ncm->port.func.free_func = ncm_free; | ||
1459 | |||
1460 | ncm->port.wrap = ncm_wrap_ntb; | ||
1461 | ncm->port.unwrap = ncm_unwrap_ntb; | ||
1462 | |||
1463 | return &ncm->port.func; | ||
1464 | } | ||
1465 | |||
1466 | DECLARE_USB_FUNCTION_INIT(ncm, ncm_alloc_inst, ncm_alloc); | ||
1467 | MODULE_LICENSE("GPL"); | ||
1468 | MODULE_AUTHOR("Yauheni Kaliuta"); | ||
1469 | |||
1470 | #endif | ||
1471 | |||
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index e411135b21e5..e2f97eecd7ce 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c | |||
@@ -36,6 +36,7 @@ | |||
36 | * the runtime footprint, and giving us at least some parts of what | 36 | * the runtime footprint, and giving us at least some parts of what |
37 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | 37 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. |
38 | */ | 38 | */ |
39 | #define USB_FNCM_INCLUDED | ||
39 | #include "f_ncm.c" | 40 | #include "f_ncm.c" |
40 | 41 | ||
41 | /*-------------------------------------------------------------------------*/ | 42 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/gadget/u_ncm.h b/drivers/usb/gadget/u_ncm.h new file mode 100644 index 000000000000..1e22b5fa844b --- /dev/null +++ b/drivers/usb/gadget/u_ncm.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * u_ncm.h | ||
3 | * | ||
4 | * Utility definitions for the ncm function | ||
5 | * | ||
6 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_NCM_H | ||
17 | #define U_NCM_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | struct f_ncm_opts { | ||
22 | struct usb_function_instance func_inst; | ||
23 | struct net_device *net; | ||
24 | bool bound; | ||
25 | }; | ||
26 | |||
27 | #endif /* U_NCM_H */ | ||