コード例 #1
0
ファイル: blan-if.c プロジェクト: R0-Developers/YP-R0_Kernel
int blan_start_recv_endpoint(struct usbd_function_instance *function_instance,
                int endpoint_index, otg_atomic_t *recv_urbs_started, char *msg)
{
        struct usb_network_private *npd = function_instance->privdata;
        int i;
        int hs = usbd_high_speed(function_instance);
        int alloc_length = usbd_endpoint_transferSize(function_instance, endpoint_index, hs);

        if (TRACE_VERBOSE)
                TRACE_MSG4(NTT, "endpoint_index: %d recv_urbs_started: %d alloc_length: %d %s",
                                endpoint_index, otg_atomic_read(recv_urbs_started), alloc_length, msg);

        while (otg_atomic_read(recv_urbs_started) < npd->max_recv_urbs ) {
                u8 *os_buffer = NULL;
                void *os_data = NULL;
                struct usbd_urb *urb;

                #ifdef DEBUG_CRC_SEEN
                if (npd->seen_crc_error) {
                        TRACE_MSG0(NTT, "CRC ERROR NOT RESTARTING");
                        break;
                }
                #endif /* DEBUG_CRC_SEEN */

                /* get os buffer - os_buffer is data, os_data is the os data structure */
                os_data = net_os_alloc_buffer(function_instance, &os_buffer, alloc_length);

                /* allocate urb with no buffer */
                /*allocate urb without buffer */
                urb = usbd_alloc_urb(function_instance, endpoint_index, 0, net_fd_recv_urb2);

                /* start urb with buffer pointing at the os_buffer in os_data structure */
                if (os_buffer && urb) {

                        urb->function_privdata = os_data;
                        urb->buffer = os_buffer;
                        urb->flags |= npd->recv_urb_flags;
                        urb->alloc_length = urb->buffer_length = alloc_length;
                        if (usbd_start_out_urb(urb)) {
                                net_os_dealloc_buffer(function_instance, os_data, os_buffer);
                                urb->function_privdata = NULL;
                                urb->buffer = NULL;
                                usbd_free_urb(urb);
                        }
                        otg_atomic_inc(recv_urbs_started);
                        continue;
                }
                TRACE_MSG1(NTT, "recv_urbs_started: %d FAILED EARLY", otg_atomic_read(recv_urbs_started));

                if (os_buffer || os_data)
                        net_os_dealloc_buffer(function_instance, os_data, os_buffer);
                if (urb)
                        urb->buffer = NULL;
                        usbd_free_urb(urb);
                break;
        }
        if (TRACE_VERBOSE)
                TRACE_MSG1(NTT, "recv_urbs_started: %d", otg_atomic_read(recv_urbs_started));
        return 0;
}
コード例 #2
0
ファイル: ecm-if.c プロジェクト: R0-Developers/YP-R0_Kernel
/*! net_fd_start_recv_ecm - start recv urb(s)
 *
 * @param function_instance - pointer to this function instance
 * @return none
 */
int net_fd_start_recv_ecm(struct usbd_function_instance *function_instance)
{
        struct usb_network_private *npd = function_instance->privdata;
        int i;
        int network_start_urbs = NETWORK_START_URBS;
        int hs = usbd_high_speed(function_instance);
        int endpoint_index = BULK_OUT_A;

        if (hs)
                network_start_urbs = NETWORK_START_URBS * 3;


        for (i = 0; i < network_start_urbs; i++) {
                struct usbd_urb *urb;
                BREAK_IF(!(urb = usbd_alloc_urb(function_instance, endpoint_index,
                                                usbd_endpoint_transferSize(function_instance, endpoint_index, hs),
                                                net_fd_recv_urb)));
                TRACE_MSG5(NTT,"i: %d urb: %p priv: %p npd: %p function: %p",
                                i, urb, urb->function_privdata, npd, function_instance);

                //urb->function_privdata = npd;
                if (usbd_start_out_urb(urb)) {
                        urb->function_privdata = NULL;
                        usbd_free_urb(urb);
                }
        }
        return 0;
}
コード例 #3
0
ファイル: blan-if.c プロジェクト: R0-Developers/YP-R0_Kernel
/*! net_fd_recv_urb2 - callback to process a received URB
 *
 * @param urb - pointer to copy of received urb,
 * @param rc - receiving urb result code
 *
 * @return non-zero for failure.
 */
int net_fd_recv_urb2(struct usbd_urb *urb, int rc)
{
        struct usbd_function_instance *function_instance = urb->function_instance;
        struct usb_network_private *npd = function_instance->privdata;
        int hs = usbd_high_speed(function_instance);
        int endpoint_index = urb->endpoint_index;

        #ifndef CONFIG_OTG_NETWORK_DOUBLE_OUT
        int recv_index = 0;
        #else /* CONFIG_OTG_NETWORK_DOUBLE_OUT */
        int recv_index = (endpoint_index == BULK_OUT_A) ? 0 : 1;
        #endif /* CONFIG_OTG_NETWORK_DOUBLE_OUT */
        int alloc_length = usbd_endpoint_transferSize(function_instance, endpoint_index, hs);
        int status = urb->status;

        void *os_data;
        u8 *os_buffer;


        if (TRACE_VERY_VERBOSE) {

                TRACE_MSG4(NTT, "status: %d actual_length: %d bus status: %d device_state: %d",
                                urb->status, urb->actual_length,
                                usbd_get_device_status(function_instance), usbd_get_device_state(function_instance)
                                );

                TRACE_NRECV(NTT, 32, urb->buffer);
                TRACE_MSG0(NTT, "--");
                TRACE_RECV(NTT, urb->actual_length, urb->buffer);
        }


        otg_atomic_dec(&npd->recv_urbs_started[recv_index]);

        /* process the data */
        if (urb->status == USBD_URB_OK)
                npd->net_recv_urb(urb, rc);

        if (urb->status == USBD_URB_CANCELLED)
                net_os_dealloc_buffer(function_instance, urb->function_privdata, urb->buffer);

        /* disconnect os_data buffer from urb */
        urb->function_privdata = NULL;
        urb->buffer = NULL;
        urb->function_instance = NULL;
        urb->status = USBD_URB_OK;
        usbd_free_urb(urb);

        if ((USBD_OK == usbd_get_device_status(function_instance)) &&
                        (STATE_CONFIGURED == usbd_get_device_state(function_instance))) {

                blan_start_recv(function_instance);
        }
        else {
                TRACE_MSG0(NTT, "NOT RESTARTING");
        }

        return 0;
}
コード例 #4
0
ファイル: ecm-if.c プロジェクト: R0-Developers/YP-R0_Kernel
/*! net_fd_start_xmit_nocrc
 * @brief - start sending a buffer
 *
 * @param function_instance - pointer to this function instance
 * @param buffer buffer containing data to send
 * @param len  - length of data to send
 * @param data instance data
 * @return: 0 if all OK
 *         -EINVAL, -EUNATCH, -ENOMEM
 *         rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above)
 *         Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped.
 */
int net_fd_start_xmit_nocrc (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data)
{
        struct usb_network_private *npd = function_instance->privdata;
        struct usbd_urb *urb = NULL;
        int rc;
        int in_pkt_sz;
        u8 *cp;
        u32 crc;
        #ifndef CONFIG_OTG_NETWORK_DOUBLE_IN
        int xmit_index = 0;
        int endpoint_index = BULK_IN_A;
        #else /* CONFIG_OTG_NETWORK_DOUBLE_IN */
        int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1]))
                ? 0 : 1;
        int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A;
        #endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */

        TRACE_MSG7(NTT,"npd: %p function: %p flags: %04x len: %d endpoint_index: %d xmit_started: %d %d",
                        npd, function_instance, npd->flags, len, endpoint_index,
                        otg_atomic_read(&npd->xmit_urbs_started[0]), otg_atomic_read(&npd->xmit_urbs_started[1]));

        in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, endpoint_index, usbd_high_speed(function_instance));

        /* allocate urb 5 bytes larger than required */
        if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + in_pkt_sz, net_fd_urb_sent_bulk ))) {
                u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance));
                TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa);
                printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa);
                return -ENOMEM;
        }

        urb->actual_length = len;

        memcpy (urb->buffer, buffer, len);
        urb->function_privdata = data;
        urb->actual_length = len;
        otg_atomic_add(urb->actual_length, &npd->queued_bytes);
        otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]);
        if ((rc = usbd_start_in_urb (urb))) {
                TRACE_MSG1(NTT,"FAILED: %d", rc);
                printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc);
                urb->function_privdata = NULL;
                otg_atomic_sub(urb->actual_length, &npd->queued_bytes);
                otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]);
                usbd_free_urb (urb);
                return rc;
        }
        return 0;
}
コード例 #5
0
/* Comment    : Must be called before any other devi_hid... function                */
void devi_unregister_usb_client(void * h)
{
   int rc;
   pModule_data_t pModule = (pModule_data_t)h;
   struct timespec t;
   
   assert(pModule);

   
   if(pModule -> ep_int)
     {
     usbd_reset_pipe(pModule -> ep_int);
     usbd_abort_pipe(pModule -> ep_int);
     }

   if(pModule -> ep_cntl)
     usbd_abort_pipe(pModule -> ep_cntl);

   if(pModule -> urb)
     usbd_free_urb(pModule -> urb);
   
   if(pModule -> ep_int_buf)
     usbd_free(pModule -> ep_int_buf);
   
   if(pModule -> ep_cnt_buf)
     usbd_free(pModule -> ep_cnt_buf);

   sleep(1);
   
   if(EOK != (rc = usbd_detach(pModule -> pDevice)))
     {
     if(verbosity)
	fprintf(stderr, "Detach device: error %i\n", rc);
     }
   
   clock_gettime(CLOCK_REALTIME, &t);
   t.tv_sec += MAX_TIME_WAIT;
   if(EOK !=  pthread_mutex_timedlock(&mod_mutex, &t))
      return ;
   
   LIST_REMOVE(pModule, lst_conn);
  
   pthread_mutex_unlock(&mod_mutex);

   free(pModule);

}
コード例 #6
0
/* Return     : None                                                                */
void removal( struct usbd_connection * pConnection, usbd_device_instance_t * pInstance )
{
   struct usbd_device	* pDevice;
   pModule_data_t pModule;
   int rc;

   if(NULL != ( pDevice = usbd_device_lookup( pConnection, pInstance )))
      {
      pModule = usbd_device_extra( pDevice );
      if( pModule -> ep_int ) 
	   {						// Stop the Interrupt In endpoint
	   usbd_abort_pipe( pModule -> ep_int );        // Abort pipe
	   usbd_free_urb( pModule -> urb );             // Free request block
	   usbd_free( pModule -> ep_int_buf );
	   if( rc = usbd_detach( pModule -> pDevice ) ) 
		fprintf( stderr, "usbd_detach %i\n", rc );
	   }
      }
}
コード例 #7
0
/* Return     : EOK if ok, error code on error                                      */
int devi_output_control(void * pHandle, pControlRequest pRequest, void * data, int nLen)
{
   int rc = EOK;
   struct usbd_urb * pUrb;
   void * pLocalData = NULL;
   pModule_data_t pModule = (pModule_data_t)pHandle;

   if(NULL == pModule -> ep_cntl)
      return EINVAL;

   if((pRequest -> dir & URB_DIR_OUT) && (nLen > pModule -> ep_cnt_size)) // Too big buffer
      return EINVAL;
   
   if( pUrb = usbd_alloc_urb( NULL ) ) // Allocate request block
      {
      if((pRequest -> dir & URB_DIR_OUT) && (NULL != data) && (nLen > 0) )
	 memcpy(pModule -> ep_cnt_buf, data, nLen); // Take data to USB -allocated buffer
      // Setup vendor request block
      usbd_setup_vendor( 
	      pUrb, 
	      pRequest -> dir, // Direction
	      pRequest -> req, // Device specific request
	      pRequest -> type | 
	      pRequest -> rec, // Type | recipient
	      pRequest -> value, // Request specific
	      pRequest -> index, // Request specific 
	      pModule -> ep_cnt_buf,
	      nLen );
      rc = usbd_io( pUrb, pModule -> ep_cntl, NULL, pModule, USBD_TIME_INFINITY ) ;
      // Delete request block
      usbd_free_urb( pUrb );

      if((pRequest -> dir & URB_DIR_IN) && (EOK == rc))  // Take data from USB -allocated buffer
	    memcpy(data, pLocalData, min(nLen, pModule -> ep_cnt_size));
      }
   else 
      rc = ENOMEM;

   return( rc );
   
}
コード例 #8
0
ファイル: blan-if.c プロジェクト: R0-Developers/YP-R0_Kernel
/*! blan_fd_device_request
 *  @brief process a received SETUP URB
 *
 * Processes a received setup packet and CONTROL WRITE data.
 * Results for a CONTROL READ are placed in urb->buffer.
 *
 * @param function_instance - pointer to this function instance
 * @param request - received request to interface or endpoint
 * @return non-zero for failure.
 */
int blan_fd_device_request (struct usbd_function_instance *function_instance, struct usbd_device_request *request)
{
        struct usb_network_private *npd = function_instance->privdata;
        struct usbd_urb *urb;
        int index;

        /* Verify that this is a USB Class request per CDC specification or a vendor request.
         */
        RETURN_ZERO_IF (!(request->bmRequestType & (USB_REQ_TYPE_CLASS | USB_REQ_TYPE_VENDOR)));

        /* Determine the request direction and process accordingly
         */
        switch (request->bmRequestType & (USB_REQ_DIRECTION_MASK | USB_REQ_TYPE_MASK)) {

        case USB_REQ_HOST2DEVICE | USB_REQ_TYPE_VENDOR:

                switch (request->bRequest) {
                case MCCI_ENABLE_CRC:
                        //if (make_crc_table())
                        //        return -EINVAL;
                        //npd->encapsulation = simple_crc;
                        return 0;

                case BELCARRA_PING:
                        TRACE_MSG1(NTT,"H2D VENDOR IP: %08x", npd->ip_addr);
                        if ((npd->network_type == network_blan))
                                net_os_send_notification_later(function_instance);
                        break;

                #if !defined(CONFIG_OTG_NETWORK_BLAN_DO_NOT_SETTIME) || !defined(CONFIG_OTG_NETWORK_SAFE_DO_NOT_SETTIME)
                case BELCARRA_SETTIME:
                        npd->rfc868time = ntohl( request->wValue << 16 | request->wIndex);
                        net_os_settime(function_instance, npd->rfc868time);
                        break;
                #endif
                case BELCARRA_SETIP:
                        #ifdef OTG_BIG_ENDIAN
                        npd->ip_addr = ntohl( request->wValue | request->wIndex<< 16 );
                        #else /* OTG_BIG_ENDIAN */
                        npd->ip_addr = ntohl( request->wValue << 16 | request->wIndex);
                        #endif /* OTG_BIG_ENDIAN */
                        TRACE_MSG1(NTT, "npd->ip_addr: %08x", npd->ip_addr);
                        // XXX need to get in correct order here
                        // XXX what about locally set mac addr
                        // XXX UNLESS(npd->local_dev_set) {
                        if (!(npd->override_MAC)) {
                                npd->local_dev_addr[0] = 0xfe | 0x02;           /* locally administered */
                                npd->local_dev_addr[1] = 0x00;
                                npd->local_dev_addr[2] = (npd->ip_addr >> 24) & 0xff;
                                npd->local_dev_addr[3] = (npd->ip_addr >> 16) & 0xff;
                                npd->local_dev_addr[4] = (npd->ip_addr >> 8) & 0xff;
                                npd->local_dev_addr[5] = (npd->ip_addr >> 0) & 0xff;
                         }
                        // XXX }
                        break;

                case BELCARRA_SETMSK:
                        #ifdef OTG_BIG_ENDIAN
                        npd->network_mask = ntohl( request->wValue | request->wIndex << 16);
                        #else /* OTG_BIG_ENDIAN */
                        npd->network_mask = ntohl( request->wValue << 16 | request->wIndex);
                        #endif /* OTG_BIG_ENDIAN */
                        TRACE_MSG1(NTT, "npd->network_mask: %08x", npd->network_mask);
                        break;

                case BELCARRA_SETROUTER:
                        #ifdef OTG_BIG_ENDIAN
                        npd->router_ip = ntohl( request->wValue | request->wIndex << 16);
                        #else /* OTG_BIG_ENDIAN */
                        npd->router_ip = ntohl( request->wValue << 16 | request->wIndex);
                        #endif /* OTG_BIG_ENDIAN */
                        TRACE_MSG1(NTT, "npd->router_ip: %08x", npd->router_ip);
                        break;

                case BELCARRA_SETDNS:
                        #ifdef OTG_BIG_ENDIAN
                        npd->dns_server_ip = ntohl( request->wValue | request->wIndex < 16);
                        #else /* OTG_BIG_ENDIAN */
                        npd->dns_server_ip = ntohl( request->wValue << 16 | request->wIndex);
                        #endif /* OTG_BIG_ENDIAN */
                        break;
                #ifdef CONFIG_OTG_NETWORK_BLAN_FERMAT
                case BELCARRA_SETFERMAT:
                        npd->fermat = 1;
                        break;
                #endif
                #ifdef CONFIG_OTG_NETWORK_BLAN_HOSTNAME
                case BELCARRA_HOSTNAME:
                        TRACE_MSG0(NTT,"HOSTNAME");
                        RETURN_EINVAL_IF(!(urb = usbd_alloc_urb_ep0(function_instance, le16_to_cpu(request->wLength),
                                                       blant_fd_urb_received_ep0) ));

                        RETURN_ZERO_IF(!usbd_start_out_urb(urb));                  // return if no error
                        usbd_free_urb(urb);                                  // de-alloc if error
                        return -EINVAL;
                #endif
                #ifdef CONFIG_OTG_NETWORK_BLAN_DATA_NOTIFY_OK
                case BELCARRA_DATA_NOTIFY:
                        TRACE_MSG0(NTT,"DATA NOTIFY");
                        npd->data_notify = 1;
                        return -EINVAL;
                #endif
                }
                switch (request->bRequest) {
                case BELCARRA_SETIP:
                case BELCARRA_SETMSK:
                case BELCARRA_SETROUTER:
                        TRACE_MSG5(NTT, "npd->network_mask: %08x npd->ip_addr: %08x npd->router_ip: %08x flags: %08x %s",
                                        npd->network_mask, npd->ip_addr, npd->router_ip, npd->flags,
                                        (npd->flags & NETWORK_CONFIGURED) ? "CONFIGURED" : "");

                        BREAK_UNLESS (npd->network_mask && npd->ip_addr && npd->router_ip && (npd->flags & NETWORK_CONFIGURED));
                        // let the os layer know, if it's interested.
                        #ifdef CONFIG_OTG_NETWORK_BLAN_AUTO_CONFIG
                        net_os_config(function_instance);
                        net_os_hotplug(function_instance);
                        #endif /* CONFIG_OTG_NETWORK_BLAN_AUTO_CONFIG */
                        break;
                }
                return 0;
        default:
                break;
        }
コード例 #9
0
ファイル: blan-if.c プロジェクト: R0-Developers/YP-R0_Kernel
/*! net_fd_start_xmit_mdlm
 * @brief - start sending a buffer
 *
 * @param function_instance - function instance pointer
 * @param buffer
 * @param len
 * @param data
 *
 * @return: 0 if all OK
 *         -EINVAL, -EUNATCH, -ENOMEM
 *         rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above)
 *         Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped.
 */
int net_fd_start_xmit_mdlm (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data)
{
        struct usb_network_private *npd = function_instance->privdata;
        struct usbd_urb *urb = NULL;
        int rc;
        u32 crc;

        #ifndef CONFIG_OTG_NETWORK_DOUBLE_IN
        int xmit_index = 0;
        int endpoint_index = BULK_IN_A;
        #else /* CONFIG_OTG_NETWORK_DOUBLE_IN */
        int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1]))
                ? 0 : 1;
        int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A;
        #endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */

        int in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, xmit_index, usbd_high_speed(function_instance));

        if (TRACE_VERBOSE)
                TRACE_MSG8(NTT,"npd: %p flags: %04x len: %d endpoint_index: %d "
                                "xmit_index: %d xmit_started: %d %d in_pkt_sz: %d",
                                npd, npd->flags, len, endpoint_index, xmit_index, otg_atomic_read(&npd->xmit_urbs_started[0]),
                                otg_atomic_read(&npd->xmit_urbs_started[1]), in_pkt_sz);

        #if defined(CONFIG_OTG_NETWORK_BLAN_CRC) || defined(CONFIG_OTG_NETWORK_SAFE_CRC)
        /* allocate urb 5 bytes larger than required */
        if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + 4 + in_pkt_sz, net_fd_urb_sent_bulk ))) {
                u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance));
                TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa);
                return -ENOMEM;
        }

        urb->actual_length = len;

        /* copy and crc len bytes */
        crc = crc32_copy(urb->buffer, buffer, len, CRC32_INIT);

        if ((urb->actual_length % in_pkt_sz) == (in_pkt_sz - 4)) {
                /* no longer in Kconfig - change undef to define to active padbyte */
                #undef CONFIG_OTG_NETWORK_PADBYTE
                #ifdef CONFIG_OTG_NETWORK_PADBYTE
                // add a pad byte if required to ensure a short packet, usbdnet driver
                // will correctly handle pad byte before or after CRC, but the MCCI driver
                // wants it before the CRC.
                crc = crc32_pad(urb->buffer + urb->actual_length, 1, crc);
                urb->actual_length++;
                #else /* CONFIG_OTG_NETWORK_PADBYTE */
                urb->flags |= USBD_URB_SENDZLP;
                TRACE_MSG2(NTT,"setting ZLP: urb: %p flags: %x", urb, urb->flags);
                #endif /* CONFIG_OTG_NETWORK_PADBYTE */
        }
        crc = ~crc;
        urb->buffer[urb->actual_length++] = crc & 0xff;
        urb->buffer[urb->actual_length++] = (crc >> 8) & 0xff;
        urb->buffer[urb->actual_length++] = (crc >> 16) & 0xff;
        urb->buffer[urb->actual_length++] = (crc >> 24) & 0xff;

        #if defined(CONFIG_OTG_NETWORK_BLAN_FERMAT)
        if (npd->fermat) fermat_encode(urb->buffer, urb->actual_length);
        #endif

        #else /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/

        /* allocate urb with no buffer */
        #ifdef CONFIG_OTG_NETWORK_XMIT_OS
        if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, 0, net_fd_urb_sent_bulk ))) {
                u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance));
                TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa);
                return -ENOMEM;
        }
        urb->actual_length = len;
        urb->buffer = buffer;
        #else /* CONFIG_OTG_NETWORK_XMIT_OS */
        if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + 4 + in_pkt_sz, net_fd_urb_sent_bulk ))) {
                u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance));
                TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa);
                printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa);
                return -ENOMEM;
        }
        urb->actual_length = len;
        memcpy (urb->buffer, buffer, len);
        #endif /* CONFIG_OTG_NETWORK_XMIT_OS */

        urb->flags |= ((urb->actual_length % in_pkt_sz) == 0) ? USBD_URB_SENDZLP : 0;

        #endif /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/

        if (TRACE_VERBOSE)
                TRACE_MSG3(NTT,"urb: %p buf: %p priv: %p", urb, data, urb->function_privdata);
        urb->function_privdata = data;

        otg_atomic_add(urb->actual_length, &npd->queued_bytes);
        otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]);
        if ((rc = usbd_start_in_urb (urb))) {

                TRACE_MSG1(NTT,"FAILED: %d", rc);
                printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc);
                urb->function_privdata = NULL;
                otg_atomic_sub(urb->actual_length, &npd->queued_bytes);
                otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]);
                usbd_free_urb (urb);

                return rc;
        }
        return 0;
}