Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 1449 lines 38 kB view raw
1/* 2 * RNDIS MSG parser 3 * 4 * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $ 5 * 6 * Authors: Benedikt Spranger, Pengutronix 7 * Robert Schwebel, Pengutronix 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * version 2, as published by the Free Software Foundation. 12 * 13 * This software was originally developed in conformance with 14 * Microsoft's Remote NDIS Specification License Agreement. 15 * 16 * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de> 17 * Fixed message length bug in init_response 18 * 19 * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de> 20 * Fixed rndis_rm_hdr length bug. 21 * 22 * Copyright (C) 2004 by David Brownell 23 * updates to merge with Linux 2.6, better match RNDIS spec 24 */ 25 26#include <linux/config.h> 27#include <linux/module.h> 28#include <linux/moduleparam.h> 29#include <linux/kernel.h> 30#include <linux/errno.h> 31#include <linux/version.h> 32#include <linux/init.h> 33#include <linux/list.h> 34#include <linux/proc_fs.h> 35#include <linux/netdevice.h> 36 37#include <asm/io.h> 38#include <asm/byteorder.h> 39#include <asm/system.h> 40#include <asm/unaligned.h> 41 42 43#undef RNDIS_PM 44#undef RNDIS_WAKEUP 45#undef VERBOSE 46 47#include "rndis.h" 48 49 50/* The driver for your USB chip needs to support ep0 OUT to work with 51 * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). 52 * 53 * Windows hosts need an INF file like Documentation/usb/linux.inf 54 * and will be happier if you provide the host_addr module parameter. 55 */ 56 57#if 0 58#define DEBUG(str,args...) do { \ 59 if (rndis_debug) \ 60 printk(KERN_DEBUG str , ## args ); \ 61 } while (0) 62static int rndis_debug = 0; 63 64module_param (rndis_debug, int, 0); 65MODULE_PARM_DESC (rndis_debug, "enable debugging"); 66 67#else 68 69#define rndis_debug 0 70#define DEBUG(str,args...) do{}while(0) 71#endif 72 73#define RNDIS_MAX_CONFIGS 1 74 75 76static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS]; 77 78/* Driver Version */ 79static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1); 80 81/* Function Prototypes */ 82static rndis_resp_t *rndis_add_response (int configNr, u32 length); 83 84 85/* supported OIDs */ 86static const u32 oid_supported_list [] = 87{ 88 /* the general stuff */ 89 OID_GEN_SUPPORTED_LIST, 90 OID_GEN_HARDWARE_STATUS, 91 OID_GEN_MEDIA_SUPPORTED, 92 OID_GEN_MEDIA_IN_USE, 93 OID_GEN_MAXIMUM_FRAME_SIZE, 94 OID_GEN_LINK_SPEED, 95 OID_GEN_TRANSMIT_BLOCK_SIZE, 96 OID_GEN_RECEIVE_BLOCK_SIZE, 97 OID_GEN_VENDOR_ID, 98 OID_GEN_VENDOR_DESCRIPTION, 99 OID_GEN_VENDOR_DRIVER_VERSION, 100 OID_GEN_CURRENT_PACKET_FILTER, 101 OID_GEN_MAXIMUM_TOTAL_SIZE, 102 OID_GEN_MEDIA_CONNECT_STATUS, 103 OID_GEN_PHYSICAL_MEDIUM, 104#if 0 105 OID_GEN_RNDIS_CONFIG_PARAMETER, 106#endif 107 108 /* the statistical stuff */ 109 OID_GEN_XMIT_OK, 110 OID_GEN_RCV_OK, 111 OID_GEN_XMIT_ERROR, 112 OID_GEN_RCV_ERROR, 113 OID_GEN_RCV_NO_BUFFER, 114#ifdef RNDIS_OPTIONAL_STATS 115 OID_GEN_DIRECTED_BYTES_XMIT, 116 OID_GEN_DIRECTED_FRAMES_XMIT, 117 OID_GEN_MULTICAST_BYTES_XMIT, 118 OID_GEN_MULTICAST_FRAMES_XMIT, 119 OID_GEN_BROADCAST_BYTES_XMIT, 120 OID_GEN_BROADCAST_FRAMES_XMIT, 121 OID_GEN_DIRECTED_BYTES_RCV, 122 OID_GEN_DIRECTED_FRAMES_RCV, 123 OID_GEN_MULTICAST_BYTES_RCV, 124 OID_GEN_MULTICAST_FRAMES_RCV, 125 OID_GEN_BROADCAST_BYTES_RCV, 126 OID_GEN_BROADCAST_FRAMES_RCV, 127 OID_GEN_RCV_CRC_ERROR, 128 OID_GEN_TRANSMIT_QUEUE_LENGTH, 129#endif /* RNDIS_OPTIONAL_STATS */ 130 131 /* mandatory 802.3 */ 132 /* the general stuff */ 133 OID_802_3_PERMANENT_ADDRESS, 134 OID_802_3_CURRENT_ADDRESS, 135 OID_802_3_MULTICAST_LIST, 136 OID_802_3_MAC_OPTIONS, 137 OID_802_3_MAXIMUM_LIST_SIZE, 138 139 /* the statistical stuff */ 140 OID_802_3_RCV_ERROR_ALIGNMENT, 141 OID_802_3_XMIT_ONE_COLLISION, 142 OID_802_3_XMIT_MORE_COLLISIONS, 143#ifdef RNDIS_OPTIONAL_STATS 144 OID_802_3_XMIT_DEFERRED, 145 OID_802_3_XMIT_MAX_COLLISIONS, 146 OID_802_3_RCV_OVERRUN, 147 OID_802_3_XMIT_UNDERRUN, 148 OID_802_3_XMIT_HEARTBEAT_FAILURE, 149 OID_802_3_XMIT_TIMES_CRS_LOST, 150 OID_802_3_XMIT_LATE_COLLISIONS, 151#endif /* RNDIS_OPTIONAL_STATS */ 152 153#ifdef RNDIS_PM 154 /* PM and wakeup are mandatory for USB: */ 155 156 /* power management */ 157 OID_PNP_CAPABILITIES, 158 OID_PNP_QUERY_POWER, 159 OID_PNP_SET_POWER, 160 161#ifdef RNDIS_WAKEUP 162 /* wake up host */ 163 OID_PNP_ENABLE_WAKE_UP, 164 OID_PNP_ADD_WAKE_UP_PATTERN, 165 OID_PNP_REMOVE_WAKE_UP_PATTERN, 166#endif /* RNDIS_WAKEUP */ 167#endif /* RNDIS_PM */ 168}; 169 170 171/* NDIS Functions */ 172static int 173gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, 174 rndis_resp_t *r) 175{ 176 int retval = -ENOTSUPP; 177 u32 length = 4; /* usually */ 178 __le32 *outbuf; 179 int i, count; 180 rndis_query_cmplt_type *resp; 181 182 if (!r) return -ENOMEM; 183 resp = (rndis_query_cmplt_type *) r->buf; 184 185 if (!resp) return -ENOMEM; 186 187 if (buf_len && rndis_debug > 1) { 188 DEBUG("query OID %08x value, len %d:\n", OID, buf_len); 189 for (i = 0; i < buf_len; i += 16) { 190 DEBUG ("%03d: %08x %08x %08x %08x\n", i, 191 le32_to_cpup((__le32 *)&buf[i]), 192 le32_to_cpup((__le32 *)&buf[i + 4]), 193 le32_to_cpup((__le32 *)&buf[i + 8]), 194 le32_to_cpup((__le32 *)&buf[i + 12])); 195 } 196 } 197 198 /* response goes here, right after the header */ 199 outbuf = (__le32 *) &resp[1]; 200 resp->InformationBufferOffset = __constant_cpu_to_le32 (16); 201 202 switch (OID) { 203 204 /* general oids (table 4-1) */ 205 206 /* mandatory */ 207 case OID_GEN_SUPPORTED_LIST: 208 DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); 209 length = sizeof (oid_supported_list); 210 count = length / sizeof (u32); 211 for (i = 0; i < count; i++) 212 outbuf[i] = cpu_to_le32 (oid_supported_list[i]); 213 retval = 0; 214 break; 215 216 /* mandatory */ 217 case OID_GEN_HARDWARE_STATUS: 218 DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); 219 /* Bogus question! 220 * Hardware must be ready to receive high level protocols. 221 * BTW: 222 * reddite ergo quae sunt Caesaris Caesari 223 * et quae sunt Dei Deo! 224 */ 225 *outbuf = __constant_cpu_to_le32 (0); 226 retval = 0; 227 break; 228 229 /* mandatory */ 230 case OID_GEN_MEDIA_SUPPORTED: 231 DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); 232 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); 233 retval = 0; 234 break; 235 236 /* mandatory */ 237 case OID_GEN_MEDIA_IN_USE: 238 DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); 239 /* one medium, one transport... (maybe you do it better) */ 240 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); 241 retval = 0; 242 break; 243 244 /* mandatory */ 245 case OID_GEN_MAXIMUM_FRAME_SIZE: 246 DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); 247 if (rndis_per_dev_params [configNr].dev) { 248 *outbuf = cpu_to_le32 ( 249 rndis_per_dev_params [configNr].dev->mtu); 250 retval = 0; 251 } 252 break; 253 254 /* mandatory */ 255 case OID_GEN_LINK_SPEED: 256 if (rndis_debug > 1) 257 DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); 258 if (rndis_per_dev_params [configNr].media_state 259 == NDIS_MEDIA_STATE_DISCONNECTED) 260 *outbuf = __constant_cpu_to_le32 (0); 261 else 262 *outbuf = cpu_to_le32 ( 263 rndis_per_dev_params [configNr].speed); 264 retval = 0; 265 break; 266 267 /* mandatory */ 268 case OID_GEN_TRANSMIT_BLOCK_SIZE: 269 DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); 270 if (rndis_per_dev_params [configNr].dev) { 271 *outbuf = cpu_to_le32 ( 272 rndis_per_dev_params [configNr].dev->mtu); 273 retval = 0; 274 } 275 break; 276 277 /* mandatory */ 278 case OID_GEN_RECEIVE_BLOCK_SIZE: 279 DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); 280 if (rndis_per_dev_params [configNr].dev) { 281 *outbuf = cpu_to_le32 ( 282 rndis_per_dev_params [configNr].dev->mtu); 283 retval = 0; 284 } 285 break; 286 287 /* mandatory */ 288 case OID_GEN_VENDOR_ID: 289 DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); 290 *outbuf = cpu_to_le32 ( 291 rndis_per_dev_params [configNr].vendorID); 292 retval = 0; 293 break; 294 295 /* mandatory */ 296 case OID_GEN_VENDOR_DESCRIPTION: 297 DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); 298 length = strlen (rndis_per_dev_params [configNr].vendorDescr); 299 memcpy (outbuf, 300 rndis_per_dev_params [configNr].vendorDescr, length); 301 retval = 0; 302 break; 303 304 case OID_GEN_VENDOR_DRIVER_VERSION: 305 DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); 306 /* Created as LE */ 307 *outbuf = rndis_driver_version; 308 retval = 0; 309 break; 310 311 /* mandatory */ 312 case OID_GEN_CURRENT_PACKET_FILTER: 313 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); 314 *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter); 315 retval = 0; 316 break; 317 318 /* mandatory */ 319 case OID_GEN_MAXIMUM_TOTAL_SIZE: 320 DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); 321 *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); 322 retval = 0; 323 break; 324 325 /* mandatory */ 326 case OID_GEN_MEDIA_CONNECT_STATUS: 327 if (rndis_debug > 1) 328 DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); 329 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 330 .media_state); 331 retval = 0; 332 break; 333 334 case OID_GEN_PHYSICAL_MEDIUM: 335 DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); 336 *outbuf = __constant_cpu_to_le32 (0); 337 retval = 0; 338 break; 339 340 /* The RNDIS specification is incomplete/wrong. Some versions 341 * of MS-Windows expect OIDs that aren't specified there. Other 342 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE! 343 */ 344 case OID_GEN_MAC_OPTIONS: /* from WinME */ 345 DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); 346 *outbuf = __constant_cpu_to_le32( 347 NDIS_MAC_OPTION_RECEIVE_SERIALIZED 348 | NDIS_MAC_OPTION_FULL_DUPLEX); 349 retval = 0; 350 break; 351 352 /* statistics OIDs (table 4-2) */ 353 354 /* mandatory */ 355 case OID_GEN_XMIT_OK: 356 if (rndis_debug > 1) 357 DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); 358 if (rndis_per_dev_params [configNr].stats) { 359 *outbuf = cpu_to_le32 ( 360 rndis_per_dev_params [configNr].stats->tx_packets - 361 rndis_per_dev_params [configNr].stats->tx_errors - 362 rndis_per_dev_params [configNr].stats->tx_dropped); 363 retval = 0; 364 } 365 break; 366 367 /* mandatory */ 368 case OID_GEN_RCV_OK: 369 if (rndis_debug > 1) 370 DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); 371 if (rndis_per_dev_params [configNr].stats) { 372 *outbuf = cpu_to_le32 ( 373 rndis_per_dev_params [configNr].stats->rx_packets - 374 rndis_per_dev_params [configNr].stats->rx_errors - 375 rndis_per_dev_params [configNr].stats->rx_dropped); 376 retval = 0; 377 } 378 break; 379 380 /* mandatory */ 381 case OID_GEN_XMIT_ERROR: 382 if (rndis_debug > 1) 383 DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); 384 if (rndis_per_dev_params [configNr].stats) { 385 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 386 .stats->tx_errors); 387 retval = 0; 388 } 389 break; 390 391 /* mandatory */ 392 case OID_GEN_RCV_ERROR: 393 if (rndis_debug > 1) 394 DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); 395 if (rndis_per_dev_params [configNr].stats) { 396 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 397 .stats->rx_errors); 398 retval = 0; 399 } 400 break; 401 402 /* mandatory */ 403 case OID_GEN_RCV_NO_BUFFER: 404 DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); 405 if (rndis_per_dev_params [configNr].stats) { 406 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 407 .stats->rx_dropped); 408 retval = 0; 409 } 410 break; 411 412#ifdef RNDIS_OPTIONAL_STATS 413 case OID_GEN_DIRECTED_BYTES_XMIT: 414 DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); 415 /* 416 * Aunt Tilly's size of shoes 417 * minus antarctica count of penguins 418 * divided by weight of Alpha Centauri 419 */ 420 if (rndis_per_dev_params [configNr].stats) { 421 *outbuf = cpu_to_le32 ( 422 (rndis_per_dev_params [configNr] 423 .stats->tx_packets - 424 rndis_per_dev_params [configNr] 425 .stats->tx_errors - 426 rndis_per_dev_params [configNr] 427 .stats->tx_dropped) 428 * 123); 429 retval = 0; 430 } 431 break; 432 433 case OID_GEN_DIRECTED_FRAMES_XMIT: 434 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); 435 /* dito */ 436 if (rndis_per_dev_params [configNr].stats) { 437 *outbuf = cpu_to_le32 ( 438 (rndis_per_dev_params [configNr] 439 .stats->tx_packets - 440 rndis_per_dev_params [configNr] 441 .stats->tx_errors - 442 rndis_per_dev_params [configNr] 443 .stats->tx_dropped) 444 / 123); 445 retval = 0; 446 } 447 break; 448 449 case OID_GEN_MULTICAST_BYTES_XMIT: 450 DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); 451 if (rndis_per_dev_params [configNr].stats) { 452 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 453 .stats->multicast*1234); 454 retval = 0; 455 } 456 break; 457 458 case OID_GEN_MULTICAST_FRAMES_XMIT: 459 DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); 460 if (rndis_per_dev_params [configNr].stats) { 461 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 462 .stats->multicast); 463 retval = 0; 464 } 465 break; 466 467 case OID_GEN_BROADCAST_BYTES_XMIT: 468 DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); 469 if (rndis_per_dev_params [configNr].stats) { 470 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 471 .stats->tx_packets/42*255); 472 retval = 0; 473 } 474 break; 475 476 case OID_GEN_BROADCAST_FRAMES_XMIT: 477 DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); 478 if (rndis_per_dev_params [configNr].stats) { 479 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 480 .stats->tx_packets/42); 481 retval = 0; 482 } 483 break; 484 485 case OID_GEN_DIRECTED_BYTES_RCV: 486 DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); 487 *outbuf = __constant_cpu_to_le32 (0); 488 retval = 0; 489 break; 490 491 case OID_GEN_DIRECTED_FRAMES_RCV: 492 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); 493 *outbuf = __constant_cpu_to_le32 (0); 494 retval = 0; 495 break; 496 497 case OID_GEN_MULTICAST_BYTES_RCV: 498 DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); 499 if (rndis_per_dev_params [configNr].stats) { 500 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 501 .stats->multicast * 1111); 502 retval = 0; 503 } 504 break; 505 506 case OID_GEN_MULTICAST_FRAMES_RCV: 507 DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); 508 if (rndis_per_dev_params [configNr].stats) { 509 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 510 .stats->multicast); 511 retval = 0; 512 } 513 break; 514 515 case OID_GEN_BROADCAST_BYTES_RCV: 516 DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); 517 if (rndis_per_dev_params [configNr].stats) { 518 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 519 .stats->rx_packets/42*255); 520 retval = 0; 521 } 522 break; 523 524 case OID_GEN_BROADCAST_FRAMES_RCV: 525 DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); 526 if (rndis_per_dev_params [configNr].stats) { 527 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 528 .stats->rx_packets/42); 529 retval = 0; 530 } 531 break; 532 533 case OID_GEN_RCV_CRC_ERROR: 534 DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); 535 if (rndis_per_dev_params [configNr].stats) { 536 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 537 .stats->rx_crc_errors); 538 retval = 0; 539 } 540 break; 541 542 case OID_GEN_TRANSMIT_QUEUE_LENGTH: 543 DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); 544 *outbuf = __constant_cpu_to_le32 (0); 545 retval = 0; 546 break; 547#endif /* RNDIS_OPTIONAL_STATS */ 548 549 /* ieee802.3 OIDs (table 4-3) */ 550 551 /* mandatory */ 552 case OID_802_3_PERMANENT_ADDRESS: 553 DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); 554 if (rndis_per_dev_params [configNr].dev) { 555 length = ETH_ALEN; 556 memcpy (outbuf, 557 rndis_per_dev_params [configNr].host_mac, 558 length); 559 retval = 0; 560 } 561 break; 562 563 /* mandatory */ 564 case OID_802_3_CURRENT_ADDRESS: 565 DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); 566 if (rndis_per_dev_params [configNr].dev) { 567 length = ETH_ALEN; 568 memcpy (outbuf, 569 rndis_per_dev_params [configNr].host_mac, 570 length); 571 retval = 0; 572 } 573 break; 574 575 /* mandatory */ 576 case OID_802_3_MULTICAST_LIST: 577 DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); 578 /* Multicast base address only */ 579 *outbuf = __constant_cpu_to_le32 (0xE0000000); 580 retval = 0; 581 break; 582 583 /* mandatory */ 584 case OID_802_3_MAXIMUM_LIST_SIZE: 585 DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); 586 /* Multicast base address only */ 587 *outbuf = __constant_cpu_to_le32 (1); 588 retval = 0; 589 break; 590 591 case OID_802_3_MAC_OPTIONS: 592 DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); 593 break; 594 595 /* ieee802.3 statistics OIDs (table 4-4) */ 596 597 /* mandatory */ 598 case OID_802_3_RCV_ERROR_ALIGNMENT: 599 DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); 600 if (rndis_per_dev_params [configNr].stats) { 601 *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] 602 .stats->rx_frame_errors); 603 retval = 0; 604 } 605 break; 606 607 /* mandatory */ 608 case OID_802_3_XMIT_ONE_COLLISION: 609 DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); 610 *outbuf = __constant_cpu_to_le32 (0); 611 retval = 0; 612 break; 613 614 /* mandatory */ 615 case OID_802_3_XMIT_MORE_COLLISIONS: 616 DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); 617 *outbuf = __constant_cpu_to_le32 (0); 618 retval = 0; 619 break; 620 621#ifdef RNDIS_OPTIONAL_STATS 622 case OID_802_3_XMIT_DEFERRED: 623 DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); 624 /* TODO */ 625 break; 626 627 case OID_802_3_XMIT_MAX_COLLISIONS: 628 DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); 629 /* TODO */ 630 break; 631 632 case OID_802_3_RCV_OVERRUN: 633 DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); 634 /* TODO */ 635 break; 636 637 case OID_802_3_XMIT_UNDERRUN: 638 DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); 639 /* TODO */ 640 break; 641 642 case OID_802_3_XMIT_HEARTBEAT_FAILURE: 643 DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); 644 /* TODO */ 645 break; 646 647 case OID_802_3_XMIT_TIMES_CRS_LOST: 648 DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); 649 /* TODO */ 650 break; 651 652 case OID_802_3_XMIT_LATE_COLLISIONS: 653 DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); 654 /* TODO */ 655 break; 656#endif /* RNDIS_OPTIONAL_STATS */ 657 658#ifdef RNDIS_PM 659 /* power management OIDs (table 4-5) */ 660 case OID_PNP_CAPABILITIES: 661 DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); 662 663 /* for now, no wakeup capabilities */ 664 length = sizeof (struct NDIS_PNP_CAPABILITIES); 665 memset(outbuf, 0, length); 666 retval = 0; 667 break; 668 case OID_PNP_QUERY_POWER: 669 DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, 670 le32_to_cpup((__le32 *) buf) - 1); 671 /* only suspend is a real power state, and 672 * it can't be entered by OID_PNP_SET_POWER... 673 */ 674 length = 0; 675 retval = 0; 676 break; 677#endif 678 679 default: 680 printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", 681 __FUNCTION__, OID); 682 } 683 if (retval < 0) 684 length = 0; 685 686 resp->InformationBufferLength = cpu_to_le32 (length); 687 r->length = length + sizeof *resp; 688 resp->MessageLength = cpu_to_le32 (r->length); 689 return retval; 690} 691 692static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, 693 rndis_resp_t *r) 694{ 695 rndis_set_cmplt_type *resp; 696 int i, retval = -ENOTSUPP; 697 struct rndis_params *params; 698 699 if (!r) 700 return -ENOMEM; 701 resp = (rndis_set_cmplt_type *) r->buf; 702 if (!resp) 703 return -ENOMEM; 704 705 if (buf_len && rndis_debug > 1) { 706 DEBUG("set OID %08x value, len %d:\n", OID, buf_len); 707 for (i = 0; i < buf_len; i += 16) { 708 DEBUG ("%03d: %08x %08x %08x %08x\n", i, 709 le32_to_cpup((__le32 *)&buf[i]), 710 le32_to_cpup((__le32 *)&buf[i + 4]), 711 le32_to_cpup((__le32 *)&buf[i + 8]), 712 le32_to_cpup((__le32 *)&buf[i + 12])); 713 } 714 } 715 716 params = &rndis_per_dev_params [configNr]; 717 switch (OID) { 718 case OID_GEN_CURRENT_PACKET_FILTER: 719 720 /* these NDIS_PACKET_TYPE_* bitflags are shared with 721 * cdc_filter; it's not RNDIS-specific 722 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: 723 * PROMISCUOUS, DIRECTED, 724 * MULTICAST, ALL_MULTICAST, BROADCAST 725 */ 726 *params->filter = (u16) le32_to_cpup((__le32 *)buf); 727 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", 728 __FUNCTION__, *params->filter); 729 730 /* this call has a significant side effect: it's 731 * what makes the packet flow start and stop, like 732 * activating the CDC Ethernet altsetting. 733 */ 734#ifdef RNDIS_PM 735update_linkstate: 736#endif 737 retval = 0; 738 if (*params->filter) { 739 params->state = RNDIS_DATA_INITIALIZED; 740 netif_carrier_on(params->dev); 741 if (netif_running(params->dev)) 742 netif_wake_queue (params->dev); 743 } else { 744 params->state = RNDIS_INITIALIZED; 745 netif_carrier_off (params->dev); 746 netif_stop_queue (params->dev); 747 } 748 break; 749 750 case OID_802_3_MULTICAST_LIST: 751 /* I think we can ignore this */ 752 DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); 753 retval = 0; 754 break; 755#if 0 756 case OID_GEN_RNDIS_CONFIG_PARAMETER: 757 { 758 struct rndis_config_parameter *param; 759 param = (struct rndis_config_parameter *) buf; 760 DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n", 761 __FUNCTION__, 762 min(cpu_to_le32(param->ParameterNameLength),80), 763 buf + param->ParameterNameOffset); 764 retval = 0; 765 } 766 break; 767#endif 768 769#ifdef RNDIS_PM 770 case OID_PNP_SET_POWER: 771 /* The only real power state is USB suspend, and RNDIS requests 772 * can't enter it; this one isn't really about power. After 773 * resuming, Windows forces a reset, and then SET_POWER D0. 774 * FIXME ... then things go batty; Windows wedges itself. 775 */ 776 i = le32_to_cpup((__force __le32 *)buf); 777 DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); 778 switch (i) { 779 case NdisDeviceStateD0: 780 *params->filter = params->saved_filter; 781 goto update_linkstate; 782 case NdisDeviceStateD3: 783 case NdisDeviceStateD2: 784 case NdisDeviceStateD1: 785 params->saved_filter = *params->filter; 786 retval = 0; 787 break; 788 } 789 break; 790 791#ifdef RNDIS_WAKEUP 792 // no wakeup support advertised, so wakeup OIDs always fail: 793 // - OID_PNP_ENABLE_WAKE_UP 794 // - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN 795#endif 796 797#endif /* RNDIS_PM */ 798 799 default: 800 printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", 801 __FUNCTION__, OID, buf_len); 802 } 803 804 return retval; 805} 806 807/* 808 * Response Functions 809 */ 810 811static int rndis_init_response (int configNr, rndis_init_msg_type *buf) 812{ 813 rndis_init_cmplt_type *resp; 814 rndis_resp_t *r; 815 816 if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; 817 818 r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); 819 if (!r) 820 return -ENOMEM; 821 resp = (rndis_init_cmplt_type *) r->buf; 822 823 resp->MessageType = __constant_cpu_to_le32 ( 824 REMOTE_NDIS_INITIALIZE_CMPLT); 825 resp->MessageLength = __constant_cpu_to_le32 (52); 826 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ 827 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); 828 resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION); 829 resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION); 830 resp->DeviceFlags = __constant_cpu_to_le32 (RNDIS_DF_CONNECTIONLESS); 831 resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3); 832 resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1); 833 resp->MaxTransferSize = cpu_to_le32 ( 834 rndis_per_dev_params [configNr].dev->mtu 835 + sizeof (struct ethhdr) 836 + sizeof (struct rndis_packet_msg_type) 837 + 22); 838 resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0); 839 resp->AFListOffset = __constant_cpu_to_le32 (0); 840 resp->AFListSize = __constant_cpu_to_le32 (0); 841 842 if (rndis_per_dev_params [configNr].ack) 843 rndis_per_dev_params [configNr].ack ( 844 rndis_per_dev_params [configNr].dev); 845 846 return 0; 847} 848 849static int rndis_query_response (int configNr, rndis_query_msg_type *buf) 850{ 851 rndis_query_cmplt_type *resp; 852 rndis_resp_t *r; 853 854 // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); 855 if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; 856 857 /* 858 * we need more memory: 859 * oid_supported_list is the largest answer 860 */ 861 r = rndis_add_response (configNr, sizeof (oid_supported_list)); 862 if (!r) 863 return -ENOMEM; 864 resp = (rndis_query_cmplt_type *) r->buf; 865 866 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); 867 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ 868 869 if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), 870 le32_to_cpu(buf->InformationBufferOffset) 871 + 8 + (u8 *) buf, 872 le32_to_cpu(buf->InformationBufferLength), 873 r)) { 874 /* OID not supported */ 875 resp->Status = __constant_cpu_to_le32 ( 876 RNDIS_STATUS_NOT_SUPPORTED); 877 resp->MessageLength = __constant_cpu_to_le32 (sizeof *resp); 878 resp->InformationBufferLength = __constant_cpu_to_le32 (0); 879 resp->InformationBufferOffset = __constant_cpu_to_le32 (0); 880 } else 881 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); 882 883 if (rndis_per_dev_params [configNr].ack) 884 rndis_per_dev_params [configNr].ack ( 885 rndis_per_dev_params [configNr].dev); 886 return 0; 887} 888 889static int rndis_set_response (int configNr, rndis_set_msg_type *buf) 890{ 891 u32 BufLength, BufOffset; 892 rndis_set_cmplt_type *resp; 893 rndis_resp_t *r; 894 895 r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); 896 if (!r) 897 return -ENOMEM; 898 resp = (rndis_set_cmplt_type *) r->buf; 899 900 BufLength = le32_to_cpu (buf->InformationBufferLength); 901 BufOffset = le32_to_cpu (buf->InformationBufferOffset); 902 903#ifdef VERBOSE 904 DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); 905 DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); 906 DEBUG("%s: InfoBuffer: ", __FUNCTION__); 907 908 for (i = 0; i < BufLength; i++) { 909 DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); 910 } 911 912 DEBUG ("\n"); 913#endif 914 915 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); 916 resp->MessageLength = __constant_cpu_to_le32 (16); 917 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ 918 if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), 919 ((u8 *) buf) + 8 + BufOffset, BufLength, r)) 920 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); 921 else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); 922 923 if (rndis_per_dev_params [configNr].ack) 924 rndis_per_dev_params [configNr].ack ( 925 rndis_per_dev_params [configNr].dev); 926 927 return 0; 928} 929 930static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) 931{ 932 rndis_reset_cmplt_type *resp; 933 rndis_resp_t *r; 934 935 r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); 936 if (!r) 937 return -ENOMEM; 938 resp = (rndis_reset_cmplt_type *) r->buf; 939 940 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); 941 resp->MessageLength = __constant_cpu_to_le32 (16); 942 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); 943 /* resent information */ 944 resp->AddressingReset = __constant_cpu_to_le32 (1); 945 946 if (rndis_per_dev_params [configNr].ack) 947 rndis_per_dev_params [configNr].ack ( 948 rndis_per_dev_params [configNr].dev); 949 950 return 0; 951} 952 953static int rndis_keepalive_response (int configNr, 954 rndis_keepalive_msg_type *buf) 955{ 956 rndis_keepalive_cmplt_type *resp; 957 rndis_resp_t *r; 958 959 /* host "should" check only in RNDIS_DATA_INITIALIZED state */ 960 961 r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type)); 962 if (!r) 963 return -ENOMEM; 964 resp = (rndis_keepalive_cmplt_type *) r->buf; 965 966 resp->MessageType = __constant_cpu_to_le32 ( 967 REMOTE_NDIS_KEEPALIVE_CMPLT); 968 resp->MessageLength = __constant_cpu_to_le32 (16); 969 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ 970 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); 971 972 if (rndis_per_dev_params [configNr].ack) 973 rndis_per_dev_params [configNr].ack ( 974 rndis_per_dev_params [configNr].dev); 975 976 return 0; 977} 978 979 980/* 981 * Device to Host Comunication 982 */ 983static int rndis_indicate_status_msg (int configNr, u32 status) 984{ 985 rndis_indicate_status_msg_type *resp; 986 rndis_resp_t *r; 987 988 if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED) 989 return -ENOTSUPP; 990 991 r = rndis_add_response (configNr, 992 sizeof (rndis_indicate_status_msg_type)); 993 if (!r) 994 return -ENOMEM; 995 resp = (rndis_indicate_status_msg_type *) r->buf; 996 997 resp->MessageType = __constant_cpu_to_le32 ( 998 REMOTE_NDIS_INDICATE_STATUS_MSG); 999 resp->MessageLength = __constant_cpu_to_le32 (20); 1000 resp->Status = cpu_to_le32 (status); 1001 resp->StatusBufferLength = __constant_cpu_to_le32 (0); 1002 resp->StatusBufferOffset = __constant_cpu_to_le32 (0); 1003 1004 if (rndis_per_dev_params [configNr].ack) 1005 rndis_per_dev_params [configNr].ack ( 1006 rndis_per_dev_params [configNr].dev); 1007 return 0; 1008} 1009 1010int rndis_signal_connect (int configNr) 1011{ 1012 rndis_per_dev_params [configNr].media_state 1013 = NDIS_MEDIA_STATE_CONNECTED; 1014 return rndis_indicate_status_msg (configNr, 1015 RNDIS_STATUS_MEDIA_CONNECT); 1016} 1017 1018int rndis_signal_disconnect (int configNr) 1019{ 1020 rndis_per_dev_params [configNr].media_state 1021 = NDIS_MEDIA_STATE_DISCONNECTED; 1022 return rndis_indicate_status_msg (configNr, 1023 RNDIS_STATUS_MEDIA_DISCONNECT); 1024} 1025 1026void rndis_uninit (int configNr) 1027{ 1028 u8 *buf; 1029 u32 length; 1030 1031 if (configNr >= RNDIS_MAX_CONFIGS) 1032 return; 1033 rndis_per_dev_params [configNr].used = 0; 1034 rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED; 1035 1036 /* drain the response queue */ 1037 while ((buf = rndis_get_next_response(configNr, &length))) 1038 rndis_free_response(configNr, buf); 1039} 1040 1041void rndis_set_host_mac (int configNr, const u8 *addr) 1042{ 1043 rndis_per_dev_params [configNr].host_mac = addr; 1044} 1045 1046/* 1047 * Message Parser 1048 */ 1049int rndis_msg_parser (u8 configNr, u8 *buf) 1050{ 1051 u32 MsgType, MsgLength; 1052 __le32 *tmp; 1053 struct rndis_params *params; 1054 1055 if (!buf) 1056 return -ENOMEM; 1057 1058 tmp = (__le32 *) buf; 1059 MsgType = le32_to_cpup(tmp++); 1060 MsgLength = le32_to_cpup(tmp++); 1061 1062 if (configNr >= RNDIS_MAX_CONFIGS) 1063 return -ENOTSUPP; 1064 params = &rndis_per_dev_params [configNr]; 1065 1066 /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for 1067 * rx/tx statistics and link status, in addition to KEEPALIVE traffic 1068 * and normal HC level polling to see if there's any IN traffic. 1069 */ 1070 1071 /* For USB: responses may take up to 10 seconds */ 1072 switch (MsgType) { 1073 case REMOTE_NDIS_INITIALIZE_MSG: 1074 DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", 1075 __FUNCTION__ ); 1076 params->state = RNDIS_INITIALIZED; 1077 return rndis_init_response (configNr, 1078 (rndis_init_msg_type *) buf); 1079 1080 case REMOTE_NDIS_HALT_MSG: 1081 DEBUG("%s: REMOTE_NDIS_HALT_MSG\n", 1082 __FUNCTION__ ); 1083 params->state = RNDIS_UNINITIALIZED; 1084 if (params->dev) { 1085 netif_carrier_off (params->dev); 1086 netif_stop_queue (params->dev); 1087 } 1088 return 0; 1089 1090 case REMOTE_NDIS_QUERY_MSG: 1091 return rndis_query_response (configNr, 1092 (rndis_query_msg_type *) buf); 1093 1094 case REMOTE_NDIS_SET_MSG: 1095 return rndis_set_response (configNr, 1096 (rndis_set_msg_type *) buf); 1097 1098 case REMOTE_NDIS_RESET_MSG: 1099 DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", 1100 __FUNCTION__ ); 1101 return rndis_reset_response (configNr, 1102 (rndis_reset_msg_type *) buf); 1103 1104 case REMOTE_NDIS_KEEPALIVE_MSG: 1105 /* For USB: host does this every 5 seconds */ 1106 if (rndis_debug > 1) 1107 DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 1108 __FUNCTION__ ); 1109 return rndis_keepalive_response (configNr, 1110 (rndis_keepalive_msg_type *) 1111 buf); 1112 1113 default: 1114 /* At least Windows XP emits some undefined RNDIS messages. 1115 * In one case those messages seemed to relate to the host 1116 * suspending itself. 1117 */ 1118 printk (KERN_WARNING 1119 "%s: unknown RNDIS message 0x%08X len %d\n", 1120 __FUNCTION__ , MsgType, MsgLength); 1121 { 1122 unsigned i; 1123 for (i = 0; i < MsgLength; i += 16) { 1124 DEBUG ("%03d: " 1125 " %02x %02x %02x %02x" 1126 " %02x %02x %02x %02x" 1127 " %02x %02x %02x %02x" 1128 " %02x %02x %02x %02x" 1129 "\n", 1130 i, 1131 buf[i], buf [i+1], 1132 buf[i+2], buf[i+3], 1133 buf[i+4], buf [i+5], 1134 buf[i+6], buf[i+7], 1135 buf[i+8], buf [i+9], 1136 buf[i+10], buf[i+11], 1137 buf[i+12], buf [i+13], 1138 buf[i+14], buf[i+15]); 1139 } 1140 } 1141 break; 1142 } 1143 1144 return -ENOTSUPP; 1145} 1146 1147int rndis_register (int (* rndis_control_ack) (struct net_device *)) 1148{ 1149 u8 i; 1150 1151 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { 1152 if (!rndis_per_dev_params [i].used) { 1153 rndis_per_dev_params [i].used = 1; 1154 rndis_per_dev_params [i].ack = rndis_control_ack; 1155 DEBUG("%s: configNr = %d\n", __FUNCTION__, i); 1156 return i; 1157 } 1158 } 1159 DEBUG("failed\n"); 1160 1161 return -1; 1162} 1163 1164void rndis_deregister (int configNr) 1165{ 1166 DEBUG("%s: \n", __FUNCTION__ ); 1167 1168 if (configNr >= RNDIS_MAX_CONFIGS) return; 1169 rndis_per_dev_params [configNr].used = 0; 1170 1171 return; 1172} 1173 1174int rndis_set_param_dev (u8 configNr, struct net_device *dev, 1175 struct net_device_stats *stats, 1176 u16 *cdc_filter) 1177{ 1178 DEBUG("%s:\n", __FUNCTION__ ); 1179 if (!dev || !stats) return -1; 1180 if (configNr >= RNDIS_MAX_CONFIGS) return -1; 1181 1182 rndis_per_dev_params [configNr].dev = dev; 1183 rndis_per_dev_params [configNr].stats = stats; 1184 rndis_per_dev_params [configNr].filter = cdc_filter; 1185 1186 return 0; 1187} 1188 1189int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) 1190{ 1191 DEBUG("%s:\n", __FUNCTION__ ); 1192 if (!vendorDescr) return -1; 1193 if (configNr >= RNDIS_MAX_CONFIGS) return -1; 1194 1195 rndis_per_dev_params [configNr].vendorID = vendorID; 1196 rndis_per_dev_params [configNr].vendorDescr = vendorDescr; 1197 1198 return 0; 1199} 1200 1201int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) 1202{ 1203 DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); 1204 if (configNr >= RNDIS_MAX_CONFIGS) return -1; 1205 1206 rndis_per_dev_params [configNr].medium = medium; 1207 rndis_per_dev_params [configNr].speed = speed; 1208 1209 return 0; 1210} 1211 1212void rndis_add_hdr (struct sk_buff *skb) 1213{ 1214 struct rndis_packet_msg_type *header; 1215 1216 if (!skb) 1217 return; 1218 header = (void *) skb_push (skb, sizeof *header); 1219 memset (header, 0, sizeof *header); 1220 header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG); 1221 header->MessageLength = cpu_to_le32(skb->len); 1222 header->DataOffset = __constant_cpu_to_le32 (36); 1223 header->DataLength = cpu_to_le32(skb->len - sizeof *header); 1224} 1225 1226void rndis_free_response (int configNr, u8 *buf) 1227{ 1228 rndis_resp_t *r; 1229 struct list_head *act, *tmp; 1230 1231 list_for_each_safe (act, tmp, 1232 &(rndis_per_dev_params [configNr].resp_queue)) 1233 { 1234 r = list_entry (act, rndis_resp_t, list); 1235 if (r && r->buf == buf) { 1236 list_del (&r->list); 1237 kfree (r); 1238 } 1239 } 1240} 1241 1242u8 *rndis_get_next_response (int configNr, u32 *length) 1243{ 1244 rndis_resp_t *r; 1245 struct list_head *act, *tmp; 1246 1247 if (!length) return NULL; 1248 1249 list_for_each_safe (act, tmp, 1250 &(rndis_per_dev_params [configNr].resp_queue)) 1251 { 1252 r = list_entry (act, rndis_resp_t, list); 1253 if (!r->send) { 1254 r->send = 1; 1255 *length = r->length; 1256 return r->buf; 1257 } 1258 } 1259 1260 return NULL; 1261} 1262 1263static rndis_resp_t *rndis_add_response (int configNr, u32 length) 1264{ 1265 rndis_resp_t *r; 1266 1267 /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ 1268 r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); 1269 if (!r) return NULL; 1270 1271 r->buf = (u8 *) (r + 1); 1272 r->length = length; 1273 r->send = 0; 1274 1275 list_add_tail (&r->list, 1276 &(rndis_per_dev_params [configNr].resp_queue)); 1277 return r; 1278} 1279 1280int rndis_rm_hdr(struct sk_buff *skb) 1281{ 1282 /* tmp points to a struct rndis_packet_msg_type */ 1283 __le32 *tmp = (void *) skb->data; 1284 1285 /* MessageType, MessageLength */ 1286 if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG) 1287 != get_unaligned(tmp++)) 1288 return -EINVAL; 1289 tmp++; 1290 1291 /* DataOffset, DataLength */ 1292 if (!skb_pull(skb, le32_to_cpu(get_unaligned(tmp++)) 1293 + 8 /* offset of DataOffset */)) 1294 return -EOVERFLOW; 1295 skb_trim(skb, le32_to_cpu(get_unaligned(tmp++))); 1296 1297 return 0; 1298} 1299 1300#ifdef CONFIG_USB_GADGET_DEBUG_FILES 1301 1302static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, 1303 void *data) 1304{ 1305 char *out = page; 1306 int len; 1307 rndis_params *param = (rndis_params *) data; 1308 1309 out += snprintf (out, count, 1310 "Config Nr. %d\n" 1311 "used : %s\n" 1312 "state : %s\n" 1313 "medium : 0x%08X\n" 1314 "speed : %d\n" 1315 "cable : %s\n" 1316 "vendor ID : 0x%08X\n" 1317 "vendor : %s\n", 1318 param->confignr, (param->used) ? "y" : "n", 1319 ({ char *s = "?"; 1320 switch (param->state) { 1321 case RNDIS_UNINITIALIZED: 1322 s = "RNDIS_UNINITIALIZED"; break; 1323 case RNDIS_INITIALIZED: 1324 s = "RNDIS_INITIALIZED"; break; 1325 case RNDIS_DATA_INITIALIZED: 1326 s = "RNDIS_DATA_INITIALIZED"; break; 1327 }; s; }), 1328 param->medium, 1329 (param->media_state) ? 0 : param->speed*100, 1330 (param->media_state) ? "disconnected" : "connected", 1331 param->vendorID, param->vendorDescr); 1332 1333 len = out - page; 1334 len -= off; 1335 1336 if (len < count) { 1337 *eof = 1; 1338 if (len <= 0) 1339 return 0; 1340 } else 1341 len = count; 1342 1343 *start = page + off; 1344 return len; 1345} 1346 1347static int rndis_proc_write (struct file *file, const char __user *buffer, 1348 unsigned long count, void *data) 1349{ 1350 rndis_params *p = data; 1351 u32 speed = 0; 1352 int i, fl_speed = 0; 1353 1354 for (i = 0; i < count; i++) { 1355 char c; 1356 if (get_user(c, buffer)) 1357 return -EFAULT; 1358 switch (c) { 1359 case '0': 1360 case '1': 1361 case '2': 1362 case '3': 1363 case '4': 1364 case '5': 1365 case '6': 1366 case '7': 1367 case '8': 1368 case '9': 1369 fl_speed = 1; 1370 speed = speed*10 + c - '0'; 1371 break; 1372 case 'C': 1373 case 'c': 1374 rndis_signal_connect (p->confignr); 1375 break; 1376 case 'D': 1377 case 'd': 1378 rndis_signal_disconnect(p->confignr); 1379 break; 1380 default: 1381 if (fl_speed) p->speed = speed; 1382 else DEBUG ("%c is not valid\n", c); 1383 break; 1384 } 1385 1386 buffer++; 1387 } 1388 1389 return count; 1390} 1391 1392#define NAME_TEMPLATE "driver/rndis-%03d" 1393 1394static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; 1395 1396#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ 1397 1398 1399int __init rndis_init (void) 1400{ 1401 u8 i; 1402 1403 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { 1404#ifdef CONFIG_USB_GADGET_DEBUG_FILES 1405 char name [20]; 1406 1407 sprintf (name, NAME_TEMPLATE, i); 1408 if (!(rndis_connect_state [i] 1409 = create_proc_entry (name, 0660, NULL))) 1410 { 1411 DEBUG ("%s :remove entries", __FUNCTION__); 1412 while (i) { 1413 sprintf (name, NAME_TEMPLATE, --i); 1414 remove_proc_entry (name, NULL); 1415 } 1416 DEBUG ("\n"); 1417 return -EIO; 1418 } 1419 1420 rndis_connect_state [i]->nlink = 1; 1421 rndis_connect_state [i]->write_proc = rndis_proc_write; 1422 rndis_connect_state [i]->read_proc = rndis_proc_read; 1423 rndis_connect_state [i]->data = (void *) 1424 (rndis_per_dev_params + i); 1425#endif 1426 rndis_per_dev_params [i].confignr = i; 1427 rndis_per_dev_params [i].used = 0; 1428 rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED; 1429 rndis_per_dev_params [i].media_state 1430 = NDIS_MEDIA_STATE_DISCONNECTED; 1431 INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue)); 1432 } 1433 1434 return 0; 1435} 1436 1437void rndis_exit (void) 1438{ 1439#ifdef CONFIG_USB_GADGET_DEBUG_FILES 1440 u8 i; 1441 char name [20]; 1442 1443 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { 1444 sprintf (name, NAME_TEMPLATE, i); 1445 remove_proc_entry (name, NULL); 1446 } 1447#endif 1448} 1449