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