Subversion Repositories Kolibri OS

Rev

Rev 1613 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. #define UHCI_USBLEGSUP          0x00c0  /* legacy support */
  3. #define UHCI_USBLEGSUP_DEFAULT  0x2000  /* only PIRQ enable set */
  4. #define UHCI_USBLEGSUP_RWC      0x8f00  /* the R/WC bits */
  5. #define UHCI_USBLEGSUP_RO       0x5040  /* R/O and reserved bits */
  6.  
  7.  
  8. #define UHCI_USBCMD                  0  /* command register */
  9. #define UHCI_USBINTR                 4  /* interrupt register */
  10. #define UHCI_USBCMD_RUN         0x0001  /* RUN/STOP bit */
  11. #define UHCI_USBCMD_HCRESET     0x0002  /* Host Controller reset */
  12. #define UHCI_USBCMD_EGSM        0x0008  /* Global Suspend Mode */
  13. #define UHCI_USBCMD_CONFIGURE   0x0040  /* Config Flag */
  14. #define UHCI_USBINTR_RESUME     0x0002  /* Resume interrupt enable */
  15.  
  16.  
  17. #define USBCMD                       0
  18. #define  USBCMD_RS              0x0001  /* Run/Stop */
  19. #define  USBCMD_HCRESET         0x0002  /* Host reset */
  20. #define  USBCMD_GRESET          0x0004  /* Global reset */
  21. #define  USBCMD_EGSM            0x0008  /* Global Suspend Mode */
  22. #define  USBCMD_FGR             0x0010  /* Force Global Resume */
  23. #define  USBCMD_SWDBG           0x0020  /* SW Debug mode */
  24. #define  USBCMD_CF              0x0040  /* Config Flag (sw only) */
  25. #define  USBCMD_MAXP            0x0080  /* Max Packet (0 = 32, 1 = 64) */
  26.  
  27. #define  USBSTS                      2
  28. #define   USBSTS_USBINT         0x0001  /* Interrupt due to IOC */
  29. #define   USBSTS_ERROR          0x0002  /* Interrupt due to error */
  30. #define   USBSTS_RD             0x0004  /* Resume Detect */
  31. #define   USBSTS_HSE            0x0008  /* Host System Error: PCI problems */
  32. #define   USBSTS_HCPE           0x0010  /* Host Controller Process Error:
  33.                                          * the schedule is buggy */
  34. #define   USBSTS_HCH            0x0020  /* HC Halted */
  35.  
  36.  
  37. #define  USBFRNUM                    6
  38. #define  USBFLBASEADD                8
  39. #define  USBSOF                     12
  40. #define  USBSOF_DEFAULT             64  /* Frame length is exactly 1 ms */
  41.  
  42. #define  USBPORTSC1                 16
  43. #define  USBPORTSC2                 18
  44.  
  45. #define  UHCI_RH_MAXCHILD            7
  46.  
  47.  
  48. /*
  49.  * Make sure the controller is completely inactive, unable to
  50.  * generate interrupts or do DMA.
  51.  */
  52. void uhci_reset_hc(hc_t *hc)
  53. {
  54.         /* Turn off PIRQ enable and SMI enable.  (This also turns off the
  55.          * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
  56.          */
  57.    pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
  58.  
  59.         /* Reset the HC - this will force us to get a
  60.          * new notification of any already connected
  61.          * ports due to the virtual disconnect that it
  62.          * implies.
  63.          */
  64.    out16(hc->iobase + UHCI_USBCMD, UHCI_USBCMD_HCRESET);
  65.    __asm__ __volatile__ ("":::"memory");
  66.  
  67.    delay(20/10);
  68.  
  69.    if (in16(hc->iobase + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
  70.        dbgprintf("HCRESET not completed yet!\n");
  71.  
  72.         /* Just to be safe, disable interrupt requests and
  73.          * make sure the controller is stopped.
  74.          */
  75.    out16(hc->iobase + UHCI_USBINTR, 0);
  76.    out16(hc->iobase + UHCI_USBCMD, 0);
  77. };
  78.  
  79. int uhci_check_and_reset_hc(hc_t *hc)
  80. {
  81.    u16_t legsup;
  82.         unsigned int cmd, intr;
  83.  
  84.         /*
  85.          * When restarting a suspended controller, we expect all the
  86.          * settings to be the same as we left them:
  87.          *
  88.          *      PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
  89.          *      Controller is stopped and configured with EGSM set;
  90.          *      No interrupts enabled except possibly Resume Detect.
  91.          *
  92.          * If any of these conditions are violated we do a complete reset.
  93.          */
  94.    legsup = pciReadWord(hc->PciTag, UHCI_USBLEGSUP);
  95.         if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
  96.        dbgprintf("%s: legsup = 0x%04x\n",__FUNCTION__, legsup);
  97.                 goto reset_needed;
  98.         }
  99.  
  100.    cmd = in16(hc->iobase + UHCI_USBCMD);
  101.    if ( (cmd & UHCI_USBCMD_RUN) ||
  102.        !(cmd & UHCI_USBCMD_CONFIGURE) ||
  103.        !(cmd & UHCI_USBCMD_EGSM))
  104.    {
  105.        dbgprintf("%s: cmd = 0x%04x\n", __FUNCTION__, cmd);
  106.                 goto reset_needed;
  107.         }
  108.  
  109.    intr = in16(hc->iobase + UHCI_USBINTR);
  110.    if (intr & (~UHCI_USBINTR_RESUME))
  111.    {
  112.        dbgprintf("%s: intr = 0x%04x\n", __FUNCTION__, intr);
  113.                 goto reset_needed;
  114.         }
  115.         return 0;
  116.  
  117. reset_needed:
  118.    dbgprintf("Performing full reset\n");
  119.    uhci_reset_hc(hc);
  120.         return 1;
  121. }
  122.  
  123. void hc_interrupt()
  124. {
  125.    hc_t   *hc;
  126.  
  127. //    printf("USB interrupt\n");
  128.  
  129.    hc = (hc_t*)hc_list.next;
  130.  
  131.    while( &hc->list != &hc_list)
  132.    {
  133.        hc_t       *htmp;
  134.        request_t  *rq;
  135.        u16_t  status;
  136.  
  137.        htmp = hc;
  138.  
  139.        hc = (hc_t*)hc->list.next;
  140.  
  141.        status = in16(htmp->iobase + USBSTS);
  142.        if (!(status & ~USBSTS_HCH))            /* shared interrupt, not mine */
  143.            continue;
  144.        out16(htmp->iobase + USBSTS, status);     /* Clear it */
  145.  
  146.        rq = (request_t*)htmp->rq_list.next;
  147.  
  148.        while( &rq->list != &htmp->rq_list)
  149.        {
  150.            request_t *rtmp;
  151.            td_t      *td;
  152.  
  153.            rtmp = rq;
  154.            rq = (request_t*)rq->list.next;
  155.  
  156.            td  = rtmp->td_tail;
  157.  
  158.            if( td->status & TD_CTRL_ACTIVE)
  159.                continue;
  160.  
  161.            list_del(&rtmp->list);
  162.  
  163.            RaiseEvent(rtmp->evh, 0, &rtmp->event);
  164.        };
  165.    }
  166. };
  167.  
  168.  
  169.  
  170. bool init_hc(hc_t *hc)
  171. {
  172.    int    port;
  173.    u32_t  ifl;
  174.    u16_t  dev_status;
  175.    td_t   *td;
  176.    int i;
  177.  
  178.    dbgprintf("\n\ninit uhci %x\n\n", hc->pciId);
  179.  
  180.    for(i=0;i<6;i++)
  181.    {
  182.        if(hc->ioBase[i]){
  183.           hc->iobase = hc->ioBase[i];
  184.       //    dbgprintf("Io base_%d 0x%x\n", i,hc->ioBase[i]);
  185.           break;
  186.        };
  187.    };
  188.  
  189.         /* The UHCI spec says devices must have 2 ports, and goes on to say
  190.          * they may have more but gives no way to determine how many there
  191.          * are.  However according to the UHCI spec, Bit 7 of the port
  192.          * status and control register is always set to 1.  So we try to
  193.          * use this to our advantage.  Another common failure mode when
  194.          * a nonexistent register is addressed is to return all ones, so
  195.          * we test for that also.
  196.          */
  197.    for (port = 0; port < 2; port++)
  198.    {
  199.        u32_t status;
  200.  
  201.        status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  202.        dbgprintf("port%d status %x\n", port, status);
  203.        if (!(status & 0x0080) || status == 0xffff)
  204.                         break;
  205.         }
  206.    dbgprintf("detected %d ports\n\n", port);
  207.  
  208.    hc->numports = port;
  209.  
  210.         /* Kick BIOS off this hardware and reset if the controller
  211.          * isn't already safely quiescent.
  212.          */
  213.     uhci_check_and_reset_hc(hc);
  214.  
  215.     hc->frame_base   = (u32_t*)KernelAlloc(4096);
  216.     hc->frame_dma    = GetPgAddr(hc->frame_base);
  217.     hc->frame_number = 0;
  218.  
  219.     hc->td_pool = dma_pool_create("uhci_td", NULL,
  220.                                   sizeof(td_t), 16, 0);
  221.     if (!hc->td_pool)
  222.     {
  223.         dbgprintf("unable to create td dma_pool\n");
  224.         goto err_create_td_pool;
  225.     }
  226.  
  227.     for (i = 0; i < UHCI_NUM_SKELQH; i++)
  228.     {
  229.     qh_t *qh = alloc_qh();
  230.  
  231.     qh->qlink = 1;
  232.     qh->qelem = 1;
  233.  
  234.         hc->qh[i] = qh;
  235.     }
  236.     for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
  237.         hc->qh[i]->qlink = hc->qh[SKEL_ASYNC]->dma | 2;
  238.  
  239. /*
  240.     td = alloc_td();
  241.  
  242.     td->link   = 1;
  243.     td->status =  (1<<24) | (1<<23) ;
  244.     td->token  = TOKEN( 0x7FF, DATA0, 0, 0, 0xE1);
  245.     td->buffer = 0;
  246.     td->bk     = NULL;
  247. */
  248.  
  249.     for (i = 0; i < 1024; i++)
  250.     {
  251.         int qnum;
  252.  
  253.         qnum = 8 - (int) __bsf( i | 1024);
  254.  
  255.         if (qnum <= 1)
  256.             qnum = 9;
  257.  
  258.         hc->frame_base[i] = hc->qh[qnum]->dma | 2;
  259.     }
  260.  
  261.     mb();
  262.  
  263.     /* Set the frame length to the default: 1 ms exactly */
  264.     out8(hc->iobase + USBSOF, USBSOF_DEFAULT);
  265.  
  266.         /* Store the frame list base address */
  267.     out32(hc->iobase + USBFLBASEADD, hc->frame_dma);
  268.  
  269.         /* Set the current frame number */
  270.     out16(hc->iobase + USBFRNUM, 0);
  271.  
  272.     out16(hc->iobase + USBSTS, 0x3F);
  273.  
  274.     out16(hc->iobase + UHCI_USBINTR, 4);
  275.  
  276.     AttachIntHandler(hc->irq_line, hc_interrupt, 0);
  277.  
  278.     pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
  279.  
  280.     out16(hc->iobase + USBCMD, USBCMD_RS | USBCMD_CF |
  281.                                USBCMD_MAXP);
  282.  
  283.     for (port = 0; port < hc->numports; ++port)
  284.         out16(hc->iobase + USBPORTSC1 + (port * 2), 0x200);
  285.     delay(100/10);
  286.  
  287.     for (port = 0; port < 2; ++port)
  288.     {
  289.         time_t timeout;
  290.  
  291.         u32_t status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  292.         dbgprintf("port%d status %x\n", port, status);
  293.  
  294.         out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
  295.  
  296.         timeout = 100/10;
  297.         while(timeout--)
  298.         {
  299.             delay(10/10);
  300.             status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  301.             if(status & 1)
  302.             {
  303.                 udev_t *dev = kmalloc(sizeof(udev_t),0);
  304.  
  305.                 out16(hc->iobase + USBPORTSC1 + (port * 2), 0x0E);
  306.  
  307.                 delay(20/10);
  308.  
  309.                 dbgprintf("enable port\n");
  310.                 status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  311.                 dbgprintf("port%d status %x\n", port, status);
  312.  
  313.                 INIT_LIST_HEAD(&dev->list);
  314.  
  315.                 dev->host     = hc;
  316.                 dev->port     = port;
  317.                 dev->ep0_size = 8;
  318.                 dev->status   = status;
  319.  
  320.                 dbgprintf("port%d connected", port);
  321.                 if(status & 4)
  322.                     dbgprintf(" enabled");
  323.                 else
  324.                     dbgprintf(" disabled");
  325.                 if(status & 0x100){
  326.                     dev->speed = 0x4000000;
  327.                     dbgprintf(" low speed\n");
  328.                 } else {
  329.                     dev->speed = 0;
  330.                     dbgprintf(" full speed\n");
  331.                 };
  332.  
  333.                 if(set_address(dev)) {
  334.                     list_add_tail(&dev->list, &newdev_list);
  335.                     hc->port_map |= 1<<port;
  336.                 }
  337.                 else {
  338.                     free(dev);
  339.                     out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
  340.                 }
  341.                 break;
  342.             };
  343.         };
  344.     };
  345.     return true;
  346.  
  347. err_create_td_pool:
  348.  
  349.     KernelFree(hc->frame_base);
  350.  
  351.     return false;
  352. };
  353.  
  354. u16_t __attribute__((aligned(16)))
  355.       req_descr[4]  = {0x0680,0x0100,0x0000,8};
  356.  
  357. /*
  358. IN(69) OUT(E1) SETUP(2D)
  359. SETUP(0) IN(1)
  360. SETUP(0) OUT(1) OUT(0) OUT(1)...IN(1)
  361. SETUP(0) IN(1) IN(0) IN(1)...OUT(0)
  362. */
  363.  
  364.  
  365. bool set_address(udev_t *dev)
  366. {
  367.     static  udev_id   = 0;
  368.     static  udev_addr = 0;
  369.     static  u16_t __attribute__((aligned(16)))
  370.             req_addr[4] = {0x0500,0x0001,0x0000,0x0000};
  371.  
  372.     static  u16_t __attribute__((aligned(16)))
  373.             req_descr[4]  = {0x0680,0x0100,0x0000,8};
  374.  
  375.     static  u32_t   data[2] __attribute__((aligned(16)));
  376.  
  377.     qh_t  *qh;
  378.     td_t  *td0, *td1, *td2;
  379.     u32_t   dev_status;
  380.     count_t timeout;
  381.     int address;
  382.  
  383.     address   = ++udev_addr;
  384.  
  385.     req_addr[1] = address;
  386.  
  387.     if( !ctrl_request(dev, &req_addr, DOUT, NULL, 0))
  388.         return false;
  389.  
  390.     dev->addr = address;
  391.     dev->id   = (++udev_id << 8) | address;
  392.  
  393.     dbgprintf("set address %d\n", address);
  394.  
  395.     data[0] = 0;
  396.     data[1] = 0;
  397.  
  398.     if( !ctrl_request(dev, &req_descr, DIN, data, 8))
  399.         return false;
  400.  
  401.     dev_descr_t *descr = (dev_descr_t*)&data;
  402.     dev->ep0_size = descr->bMaxPacketSize0;
  403.  
  404.     return true;
  405. }
  406.  
  407. request_t *create_request(udev_t *dev, endp_t *enp, u32_t dir,
  408.                           void *data, size_t req_size)
  409. {
  410.     td_t  *td, *td_prev;
  411.     addr_t data_dma;
  412.     hc_t     *hc = dev->host;
  413.     size_t  packet_size = enp->size;
  414.     size_t  size = req_size;
  415.     addr_t  td_dma;
  416.  
  417.     request_t *rq = (request_t*)kmalloc(sizeof(request_t),0);
  418.  
  419.     INIT_LIST_HEAD(&rq->list);
  420.  
  421.     rq->data = (addr_t)data;
  422.     rq->size = req_size;
  423.     rq->dev  = dev;
  424.  
  425.     if(data)
  426.         data_dma = DMA(data);
  427.  
  428.     td_prev = NULL;
  429.  
  430.     while(size > 0)
  431.     {
  432.         if ( size < packet_size)
  433.         {
  434.             packet_size = size;
  435.         };
  436.  
  437.         td = dma_pool_alloc(hc->td_pool, 0, &td_dma);
  438.         td->dma = td_dma;
  439.  
  440.         td->link = 1;
  441.  
  442.         if(rq->td_head == NULL)
  443.             rq->td_head = td;
  444.  
  445.         if( td_prev )
  446.             td_prev->link   = td->dma | 4;
  447.         td->status = TD_CTRL_ACTIVE | dev->speed;
  448.         td->token  = TOKEN(packet_size,enp->toggle,enp->address,
  449.                            dev->addr,dir);
  450.         td->buffer = data_dma;
  451.         td->bk     = td_prev;
  452.  
  453.         td_prev = td;
  454.  
  455.         data_dma+= packet_size;
  456.         size-= packet_size;
  457.         enp->toggle ^= DATA1;
  458.     };
  459.  
  460.     td->status |= TD_CTRL_IOC;
  461.     rq->td_tail = td;
  462.  
  463.     rq->evh = CreateEvent(NULL, MANUAL_DESTROY);
  464.  
  465.     if(rq->evh.handle == 0)
  466.         printf("%s: epic fail\n", __FUNCTION__);
  467.  
  468.     rq->event.code    = 0xFF000001;
  469.     rq->event.data[0] = (addr_t)rq;
  470.  
  471.     return rq;
  472. }
  473.  
  474. bool ctrl_request(udev_t *dev, void *req, u32_t pid,
  475.                   void *data, size_t req_size)
  476. {
  477.     size_t  packet_size = dev->ep0_size;
  478.     size_t  size = req_size;
  479.     u32_t   toggle = DATA1;
  480.  
  481.     td_t   *td0, *td, *td_prev;
  482.     qh_t   *qh;
  483.     addr_t  data_dma = 0;
  484.     hc_t   *hc = dev->host;
  485.  
  486.     addr_t  td_dma = 0;
  487.  
  488.     bool    retval;
  489.  
  490.  
  491.     request_t *rq = (request_t*)kmalloc(sizeof(request_t),0);
  492.  
  493.     INIT_LIST_HEAD(&rq->list);
  494.  
  495.     rq->data = (addr_t)data;
  496.     rq->size = req_size;
  497.     rq->dev  = dev;
  498.  
  499.     td0 = dma_pool_alloc(hc->td_pool, 0, &td_dma);
  500.     td0->dma = td_dma;
  501.  
  502.     dbgprintf("alloc td0 %x dma %x\n", td0, td_dma);
  503.  
  504.     td0->status = 0x00800000 | dev->speed;
  505.     td0->token  = TOKEN( 8, DATA0, 0, dev->addr, 0x2D);
  506.     td0->buffer = DMA(req);
  507.     td0->bk     = NULL;
  508.  
  509.     if(data)
  510.         data_dma = DMA(data);
  511.  
  512.     td_prev = td0;
  513.  
  514.     while(size > 0)
  515.     {
  516.         if ( size < packet_size)
  517.         {
  518.             packet_size = size;
  519.         };
  520.  
  521.         td = dma_pool_alloc(hc->td_pool, 0, &td_dma);
  522.         td->dma = td_dma;
  523.  
  524.         dbgprintf("alloc td %x dma %x\n", td, td->dma);
  525.  
  526.         td_prev->link   = td->dma | 4;
  527.         td->status = TD_CTRL_ACTIVE | dev->speed;
  528.         td->token  = TOKEN(packet_size, toggle, 0,dev->addr, pid);
  529.         td->buffer = data_dma;
  530.         td->bk     = td_prev;
  531.  
  532.         td_prev = td;
  533.  
  534.         data_dma+= packet_size;
  535.         size-= packet_size;
  536.         toggle ^= DATA1;
  537.     }
  538.  
  539.     td = dma_pool_alloc(hc->td_pool, 0, &td_dma);
  540.     td->dma = td_dma;
  541.  
  542.     dbgprintf("alloc td %x dma %x\n", td, td->dma);
  543.  
  544.     td_prev->link   = td->dma | 4;
  545.  
  546.     pid = (pid == DIN) ? DOUT : DIN;
  547.  
  548.     td->link = 1;
  549.     td->status = TD_CTRL_ACTIVE | TD_CTRL_IOC | dev->speed ;
  550.     td->token  = (0x7FF<<21)|DATA1|(dev->addr<<8)|pid;
  551.     td->buffer = 0;
  552.     td->bk     = td_prev;
  553.  
  554.     rq->td_head = td0;
  555.     rq->td_tail = td;
  556.  
  557.     rq->evh = CreateEvent(NULL, MANUAL_DESTROY);
  558.  
  559.     if(rq->evh.handle == 0)
  560.         printf("%s: epic fail\n", __FUNCTION__);
  561.  
  562.     rq->event.code    = 0xFF000001;
  563.     rq->event.data[0] = (addr_t)rq;
  564.  
  565.     u32_t efl = safe_cli();
  566.  
  567.       list_add_tail(&rq->list, &dev->host->rq_list);
  568.  
  569.     qh = dev->host->qh[SKEL_ASYNC];
  570.  
  571.     qh->qelem = td0->dma;
  572.  
  573.     mb();
  574.  
  575.     safe_sti(efl);
  576.  
  577.     WaitEvent(rq->evh.handle, rq->evh.euid);
  578.  
  579.     dbgprintf("td0 status 0x%0x\n", td0->status);
  580.     dbgprintf("td  status 0x%0x\n", td->status);
  581.  
  582.     if( (td0->status & TD_ANY_ERROR) ||
  583.         (td_prev->status & TD_ANY_ERROR) ||
  584.         (td->status & TD_ANY_ERROR))
  585.     {
  586.         u32_t dev_status = in16(dev->host->iobase + USBSTS);
  587.  
  588.         dbgprintf("\nframe %x, cmd %x status %x\n",
  589.                    in16(dev->host->iobase + USBFRNUM),
  590.                    in16(dev->host->iobase + USBCMD),
  591.                     dev_status);
  592.         dbgprintf("td0 status %x\n",td0->status);
  593.         dbgprintf("td_prev status %x\n",td_prev->status);
  594.         dbgprintf("td status %x\n",td->status);
  595.         dbgprintf("qh %x \n", qh->qelem);
  596.  
  597.         retval = false;
  598.     } else retval = true;
  599.  
  600.     qh->qelem = 1;
  601.  
  602.     mb();
  603.  
  604.     do
  605.     {
  606.         td_prev = td->bk;
  607.         dma_pool_free(hc->td_pool, td, td->dma);
  608.         td = td_prev;
  609.     }while( td != NULL);
  610.  
  611. /*
  612.     delete event;
  613. */
  614.     kfree(rq);
  615.  
  616.     return retval;
  617. };
  618.  
  619.  
  620. bool init_device(udev_t *dev)
  621. {
  622.     static  u16_t __attribute__((aligned(16)))
  623.             req_descr[4]  = {0x0680,0x0100,0x0000,18};
  624.  
  625.     static  u16_t __attribute__((aligned(16)))
  626.             req_conf[4]  = {0x0680,0x0200,0x0000,9};
  627.  
  628.     static dev_descr_t __attribute__((aligned(16))) descr;
  629.  
  630.     interface_descr_t *interface;
  631.  
  632.     u32_t  data[8];
  633.  
  634.     u8_t *dptr;
  635.     conf_descr_t      *conf;
  636.  
  637.     dbgprintf("\ninit device %x, host %x, port %d\n\n",
  638.                dev->id, dev->host->pciId, dev->port);
  639.  
  640.     if( !ctrl_request(dev, req_descr, DIN, &descr, 18))
  641.     {
  642.         dbgprintf("%s epic fail\n",__FUNCTION__);
  643.         return;
  644.     };
  645.  
  646.     dev->dev_descr = descr;
  647.  
  648.     dbgprintf("device descriptor:\n\n"
  649.               "bLength             %d\n"
  650.               "bDescriptorType     %d\n"
  651.               "bcdUSB              %x\n"
  652.               "bDeviceClass        %x\n"
  653.               "bDeviceSubClass     %x\n"
  654.               "bDeviceProtocol     %x\n"
  655.               "bMaxPacketSize0     %d\n"
  656.               "idVendor            %x\n"
  657.               "idProduct           %x\n"
  658.               "bcdDevice           %x\n"
  659.               "iManufacturer       %x\n"
  660.               "iProduct            %x\n"
  661.               "iSerialNumber       %x\n"
  662.               "bNumConfigurations  %d\n\n",
  663.               descr.bLength, descr.bDescriptorType,
  664.               descr.bcdUSB,  descr.bDeviceClass,
  665.               descr.bDeviceSubClass, descr.bDeviceProtocol,
  666.               descr.bMaxPacketSize0, descr.idVendor,
  667.               descr.idProduct, descr.bcdDevice,
  668.               descr.iManufacturer, descr.iProduct,
  669.               descr.iSerialNumber, descr.bNumConfigurations);
  670.  
  671.     req_conf[3] = 8;
  672.     if( !ctrl_request(dev, req_conf, DIN, &data, 8))
  673.         return;
  674.  
  675.     conf = (conf_descr_t*)&data;
  676.  
  677.     size_t conf_size = conf->wTotalLength;
  678.  
  679.     req_conf[3] = conf_size;
  680.     conf = malloc(conf_size);
  681.  
  682.     if( !ctrl_request(dev, req_conf, DIN, conf, conf_size))
  683.         return;
  684.  
  685.     dptr = (u8_t*)conf;
  686.     dptr+= conf->bLength;
  687.  
  688.     dbgprintf("configuration descriptor\n\n"
  689.               "bLength             %d\n"
  690.               "bDescriptorType     %d\n"
  691.               "wTotalLength        %d\n"
  692.               "bNumInterfaces      %d\n"
  693.               "bConfigurationValue %x\n"
  694.               "iConfiguration      %d\n"
  695.               "bmAttributes        %x\n"
  696.               "bMaxPower           %dmA\n\n",
  697.               conf->bLength,
  698.               conf->bDescriptorType,
  699.               conf->wTotalLength,
  700.               conf->bNumInterfaces,
  701.               conf->bConfigurationValue,
  702.               conf->iConfiguration,
  703.               conf->bmAttributes,
  704.               conf->bMaxPower*2);
  705.  
  706.         interface = (interface_descr_t*)dptr;
  707.  
  708.         switch(interface->bInterfaceClass)
  709.         {
  710.             case USB_CLASS_AUDIO:
  711.                 dbgprintf( "audio device\n");
  712.                 break;
  713.             case USB_CLASS_HID:
  714.                 dev->conf = conf;
  715.                 list_del(&dev->list);
  716.                 return init_hid(dev);
  717.  
  718.             case USB_CLASS_PRINTER:
  719.                 dbgprintf("printer\n");
  720.                 break;
  721.             case USB_CLASS_MASS_STORAGE:
  722.                 dbgprintf("mass storage device\n");
  723.                 break;
  724.             case USB_CLASS_HUB:
  725.                 dbgprintf("hub device\n");
  726.                 break;
  727.             default:
  728.                 dbgprintf("unknown device\n");
  729.         };
  730. };
  731.