Esempio n. 1
0
/*! 
 * generic_cf_modexit() - module init
 *
 * This is called by the Linux kernel; when the module is being unloaded 
 * if compiled as a module. This function is never called if the 
 * driver is linked into the kernel.
 *
 * @param void
 * @return void
 */
static void generic_cf_modexit (void)
{
        int i;
        otg_trace_invalidate_tag(GENERIC);
        for (i = 0; ; i++) {
                struct generic_config *config = generic_configs + i;

                BREAK_UNLESS(config->interface_names);

                //printk(KERN_INFO"%s: %s registered: %d\n", 
                //                __FUNCTION__, config->composite_driver.driver.name, config->registered);

                CONTINUE_UNLESS(config->registered);

                usbd_deregister_composite_function (&config->composite_driver);

                if (config->interface_list)
                        LKFREE(config->interface_list);
        }

        if (generic_config.registered)
                usbd_deregister_composite_function (&generic_config.composite_driver);

        if (generic_config.interface_list) 
                LKFREE(generic_config.interface_list);
}
Esempio n. 2
0
/*! 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;
        }
Esempio n. 3
0
/*! 
 * generic_cf_modinit() - module init
 *
 * This is called by the Linux kernel; either when the module is loaded
 * if compiled as a module, or during the system intialization if the 
 * driver is linked into the kernel.
 *
 * This function will parse module parameters if required and then register
 * the generic driver with the USB Device software.
 *
 */
static int generic_cf_modinit (void)
{
        int i;

        #if !defined(OTG_C99)
        //generic_cf_global_init();
        #endif /* defined(OTG_C99) */


        GENERIC = otg_trace_obtain_tag();

        i = MODPARM(idVendor);

        printk (KERN_INFO "Model ID is %s",MODPARM(iProduct));

#if 0
        TRACE_MSG4(GENERIC, "config_name: \"%s\" load_all: %d class_name: \"%s\" interface_names: \"%s\"",
                        MODPARM(config_name) ? MODPARM(config_name) : "", 
                        MODPARM(load_all), 
                        MODPARM(class_name) ? MODPARM(class_name) : "", 
                        MODPARM(interface_names) ? MODPARM(interface_names) : "");
#else

        TRACE_MSG5(GENERIC, "config_name: \"%s\" load_all: %d class_name: \"%s\" interface_names: \"%s\" Serial: \"%s\"",
                        generic_config_name(), 
                        MODPARM(load_all), 
                        MODPARM(class_name) ? MODPARM(class_name) : "", 
                        MODPARM(interface_names) ? MODPARM(interface_names) : "",
			MODPARM(iSerialNumber) ? MODPARM(iSerialNumber) : "");

#endif

        /* load config or configs
         */
        
        if (preset_config_name()  || MODPARM(load_all)) {

		if (preset_config_name()){
                        MODPARM(load_all) = 0;
		}

                printk (KERN_INFO "%s: config_name: \"%s\" load_all: %d\n", 
                                __FUNCTION__, generic_config_name() , MODPARM(load_all));

                /* search for named config
                 */
                for (i = 0; ; i++) {
                        struct generic_config *config = generic_configs + i;
                        BREAK_UNLESS(config->interface_names);
                        printk(KERN_INFO"%s: checking[%d] \"%s\"\n", __FUNCTION__, i, config->composite_driver.driver.name);

			if (MODPARM(iSerialNumber) && strlen(MODPARM(iSerialNumber)) &&
                            /* For the moment, we will only use serial number for msc and mtp.  I suggest we come up with a more generic
                               way to determine if a function driver needs to use the serial number. (for instance another function member. */
                            ( ( !strcmp(config->composite_driver.driver.name, "mtp")) || !strcmp(config->composite_driver.driver.name, "msc")) ){
                              config->device_description.iSerialNumber = MODPARM(iSerialNumber);
			}

                        config->device_description.iProduct = MODPARM(iProduct);

                        generic_cf_register(config, generic_config_name());
                        //printk(KERN_INFO"%s: loaded  %s\n", __FUNCTION__, config->composite_driver.driver.name);
                }
        }
        else {
                struct generic_config *config = &generic_config;

                //printk (KERN_INFO "%s: idVendor: %04x idProduct: %04x\n", __FUNCTION__, MODPARM(idVendor), MODPARM(idProduct));
                //printk (KERN_INFO "%s: class_name: \"%s\" _interface_names: \"%s\"\n", 
                //                __FUNCTION__, MODPARM(class_name), MODPARM(interface_names));

                if (MODPARM(driver_name) && strlen(MODPARM(driver_name)))
                        config->composite_driver.driver.name = MODPARM(driver_name);

                if (MODPARM(class_name) && strlen(MODPARM(class_name)))
                        config->class_name = MODPARM(class_name);

                if (MODPARM(interface_names) && strlen(MODPARM(interface_names)))
                        config->interface_names = MODPARM(interface_names);

                if (MODPARM(iConfiguration) && strlen(MODPARM(iConfiguration)))
                        config->configuration_description.iConfiguration = MODPARM(iConfiguration);

                if (MODPARM(bDeviceClass))
                        config->device_description.bDeviceClass = MODPARM(bDeviceClass);

                if (MODPARM(bDeviceSubClass))
                        config->device_description.bDeviceSubClass = MODPARM(bDeviceSubClass);

                if (MODPARM(bDeviceProtocol))
                        config->device_description.bDeviceProtocol = MODPARM(bDeviceProtocol);

                if (MODPARM(idVendor)) 
                        config->device_description.idVendor = MODPARM(idVendor);
                else
                        config->device_description.idVendor = CONFIG_OTG_GENERIC_VENDORID;

                if (MODPARM(idProduct))
                        config->device_description.idProduct = MODPARM(idProduct);
                else
                        config->device_description.idProduct = CONFIG_OTG_GENERIC_PRODUCTID;

                if (MODPARM(bcdDevice))
                        config->device_description.bcdDevice = MODPARM(bcdDevice);
                else
                        config->device_description.bcdDevice = CONFIG_OTG_GENERIC_BCDDEVICE;

                if (MODPARM(iManufacturer) && strlen(MODPARM(iManufacturer)))
                        config->device_description.iManufacturer = MODPARM(iManufacturer);
                else
                        config->device_description.iManufacturer = CONFIG_OTG_GENERIC_MANUFACTURER;

                if (MODPARM(iProduct) && strlen(MODPARM(iProduct)))
                        config->device_description.iProduct = MODPARM(iProduct);
                else
                        config->device_description.iProduct = CONFIG_OTG_GENERIC_PRODUCT_NAME;

                if (MODPARM(iSerialNumber) && strlen(MODPARM(iSerialNumber))){
                        config->device_description.iSerialNumber = MODPARM(iSerialNumber);
		}
                if (MODPARM(interface_names))
                        config->interface_names = MODPARM(interface_names);

                generic_cf_register(config, NULL);
        }
        return 0;
}
Esempio n. 4
0
/*! arc_add_buffer_to_dtd
 *
 * C.f. 39.16.5.3 - case 1: Link list is empty
 */
static void arc_add_buffer_to_dtd (struct pcd_instance *pcd, struct usbd_endpoint_instance *endpoint,
                int dir, int len, int offset)
{
        struct otg_instance     *otg = pcd->otg;
        struct usbd_urb         *urb = endpoint->active_urb;
        struct arc_private_struct *privdata = endpoint->privdata;

        u8                      hs = pcd->bus->high_speed;
        u8                      physicalEndpoint = endpoint->physicalEndpoint[hs];
        u8                      bEndpointAddress = endpoint->bEndpointAddress[hs];
        u8                      epnum = bEndpointAddress & 0x3f;
        u16                     wMaxPacketSize = endpoint->wMaxPacketSize[hs];
        struct ep_queue_head    *dQH = &udc_controller->ep_qh[2 * epnum + dir];
        struct ep_td_struct     *dtd = &(udc_controller->ep_dtd[2 * epnum + dir]);

        u32                     mask = 0;
        int                     timeout1 = 0;
        int                     timeout2 = 0;

        u32                     endptstat = -1;
        u32                     endptprime = -1;
        u32                     endptcomplete = -1;

        TRACE_MSG6(pcd->TAG, "[%2d] USBCMD: %08x ENDPTPRIME: %08x COMPLETE: %08x STATUS: %08x %s",
                        2*epnum+dir, UOG_USBCMD, UOG_ENDPTPRIME, UOG_ENDPTCOMPLETE,
                        (u32)dQH->size_ioc_int_sts, (dir == ARC_DIR_OUT) ? "OUT" : "IN");

        if (urb && urb->buffer) {

                TRACE_MSG4(pcd->TAG, "buffer: %x length: %d alloc: %d dir: %d ",
                                urb->buffer, urb->actual_length, urb->buffer_length, dir);

                /* flush cache for IN */
                if ((dir == ARC_DIR_IN) && urb->actual_length)
                        dma_cache_maint(urb->buffer, urb->actual_length, DMA_TO_DEVICE);

                /* invalidate cache for OUT */
                else if ((dir == ARC_DIR_OUT) && urb->buffer_length)
                        dma_cache_maint(urb->buffer, urb->alloc_length, DMA_FROM_DEVICE);
        }

        /* Set size and interrupt on each dtd, Clear reserved field,
         * set pointers and flush from cache, and save in cur_dqh for dtd_releases()
         */
        memset(dtd, 0, sizeof(struct ep_td_struct));
        dtd->size_ioc_sts = cpu_to_le32(((len << DTD_LENGTH_BIT_POS) | DTD_IOC | DTD_STATUS_ACTIVE));
        dtd->size_ioc_sts &= cpu_to_le32(~DTD_RESERVED_FIELDS);
        dtd->buff_ptr0 = cpu_to_le32(endpoint->active_urb ?  (u32) (virt_to_phys (endpoint->active_urb->buffer + offset)) : 0);
        dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE);
        dtd->next_td_virt = NULL;
        dma_cache_maint(dtd, sizeof(struct ep_td_struct), DMA_TO_DEVICE);
        privdata->cur_dqh = dQH;

        /* Case 1 - Step 1 - Write dQH next pointer and dQH terminate bit to 0 as single DWord */
        dQH->next_dtd_ptr = cpu_to_le32( virt_to_phys((void *)dtd) & EP_QUEUE_HEAD_NEXT_POINTER_MASK);

        /* Case 1 - Step 2 - Clear active and halt bit */
        dQH->size_ioc_int_sts &= le32_to_cpu(~(EP_QUEUE_HEAD_STATUS_ACTIVE | EP_QUEUE_HEAD_STATUS_HALT));

        dma_cache_maint(dQH, sizeof(struct ep_queue_head), DMA_TO_DEVICE);

        /* Case 1 - Step 3 - Prime endpoint by writing ENDPTPRIME */
        mask = (dir == ARC_DIR_OUT) ?  (1 << epnum) : (1 << (epnum + 16));

        /* Verify that endpoint PRIME is not set, wait if necessary. */
        for (timeout1 = 0; (UOG_ENDPTPRIME & mask) && (timeout1 ++ < 100); udelay(1));

        /* ep0 needs extra tests */
        UNLESS(epnum) {
                /* C.f. 39.16.3.2.2 Data Phase */
                UOG_ENDPTPRIME |= mask;
                for (timeout2 = 0; timeout2++ < 100; ) {
                        endptprime = UOG_ENDPTPRIME;    // order may be important
                        endptstat = UOG_ENDPTSTAT;      // we check stat after prime
                        BREAK_IF(endptstat & mask);
                        BREAK_UNLESS(endptprime & mask);
                }
                if (!(endptstat & mask) && !(endptprime & mask)) {
                        TRACE_MSG2(pcd->TAG, "[%2d] ENDPTSETUPSTAT: %04x PREMATURE FAILUURE", 2*epnum+dir, UOG_ENDPTSETUPSTAT);
                }
                TRACE_MSG6(pcd->TAG, "[%2d] ENDPTPRIME %08x ENPTSTAT: %08x mask: %08x timeout: %d:%d SET",
                                2*epnum+dir, UOG_ENDPTPRIME, UOG_ENDPTSTAT, mask, timeout1, timeout2);;
        }
        /* epn general case */
        else {