Warning, cross-references for /kernel/drivers/usb/net.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <drivers/usb/usb.h>
0019 #include <drivers/usb/uhci.h>
0020 #include <drivers/net/ethernet.h>
0021 #include <util/printf.h>
0022 #include <kernel.h>
0023 #include "sched/sched.h"
0024
0025 #define DEBUG_USB_NET
0026
0027 #ifdef DEBUG_USB_NET
0028 #define DLOG(fmt,...) DLOG_PREFIX("USB-net",fmt,##__VA_ARGS__)
0029 #else
0030 #define DLOG(fmt,...) ;
0031 #endif
0032
0033 #define CDC_TYPE_CS_INTERFACE 0x24
0034
0035 #define CDC_SUBTYPE_HEADER 0x00
0036 #define CDC_SUBTYPE_UNION 0x06
0037 #define CDC_SUBTYPE_ETHERNET 0x0F
0038
0039
0040 struct cdc_header_fundesc {
0041 uint8 bFunctionLength;
0042 uint8 bDescriptorType;
0043 uint8 bDescriptorSubtype;
0044 uint16 bcdCDC;
0045 } PACKED;
0046 typedef struct cdc_header_fundesc CDC_HEADER_FUNDESC;
0047
0048 struct cdc_union_fundesc {
0049 uint8 bFunctionLength;
0050 uint8 bDescriptorType;
0051 uint8 bDescriptorSubtype;
0052 uint8 bControlInterface;
0053 uint8 bSubordinateInterface[];
0054 } PACKED;
0055 typedef struct cdc_union_fundesc CDC_UNION_FUNDESC;
0056
0057 struct cdc_ethernet_fundesc {
0058 uint8 bFunctionLength;
0059 uint8 bDescriptorType;
0060 uint8 bDescriptorSubtype;
0061 uint8 iMACAddress;
0062 uint32 bmEthernetStatistics;
0063 uint16 wMaxSegmentSize;
0064 uint16 wNumberMCFilters;
0065 uint8 bNumberPowerFilters;
0066 } PACKED;
0067 typedef struct cdc_ethernet_fundesc CDC_ETHERNET_FUNDESC;
0068
0069 typedef union {
0070 struct {
0071 uint8 bFunctionLength;
0072 uint8 bDescriptorType;
0073 uint8 bDescriptorSubtype;
0074 };
0075 CDC_HEADER_FUNDESC header;
0076 CDC_UNION_FUNDESC cdc_union;
0077 CDC_ETHERNET_FUNDESC ethernet;
0078 } CDC_FUNDESC;
0079
0080 static inline uint8
0081 hex2byte (uint8 h[2])
0082 {
0083 return
0084 (('0' <= h[0] && h[0] <= '9') ? h[0] - '0' : h[0] - 'A' + 10) * 16 +
0085 (('0' <= h[1] && h[1] <= '9') ? h[1] - '0' : h[1] - 'A' + 10);
0086 }
0087
0088 static uint8 ethaddr[6];
0089 static uint status_ept, status_maxpkt;
0090 static uint data_ept_in, data_ept_out, data_maxpkt;
0091 static uint data_iface, data_nop_alt, data_real_alt;
0092 static USB_DEVICE_INFO *ethusbdev;
0093 static ethernet_device usbnet_ethdev;
0094
0095 static bool
0096 reset (void)
0097 {
0098 if (usb_set_interface (ethusbdev, data_nop_alt, data_iface) != 0) {
0099 DLOG ("set_interface -> nop data: failed");
0100 return FALSE;
0101 }
0102
0103 if (usb_set_interface (ethusbdev, data_real_alt, data_iface) != 0) {
0104 DLOG ("set_interface -> real data: failed");
0105 return FALSE;
0106 }
0107
0108 return TRUE;
0109 }
0110
0111 static bool
0112 get_hwaddr (uint8 addr[ETH_ADDR_LEN])
0113 {
0114 int i;
0115 for (i=0; i<ETH_ADDR_LEN; i++)
0116 addr[i] = ethaddr[i];
0117 return TRUE;
0118 }
0119
0120 static sint
0121 transmit (uint8* buf, sint len)
0122 {
0123 sint ret;
0124 uint32 act_len;
0125
0126 DLOG ("transmitting data len=%d: %.02X %.02X %.02X %.02X", len,
0127 buf[0], buf[1], buf[2], buf[3]);
0128 if (usb_bulk_transfer (ethusbdev, data_ept_out, buf, len,
0129 data_maxpkt, DIR_OUT, &act_len) == 0)
0130 ret = len;
0131 else
0132 ret = 0;
0133
0134 return ret;
0135 }
0136
0137 static void
0138 poll (void)
0139 {
0140 uint8 buffer[1600];
0141 uint32 act_len;
0142 if (usb_bulk_transfer (ethusbdev, data_ept_in, buffer, 1514,
0143 data_maxpkt, DIR_IN, &act_len) == 0) {
0144 if (act_len > 0) {
0145 DLOG ("receiving data len=%d: %.02X %.02X %.02X %.02X",
0146 act_len, buffer[0], buffer[1], buffer[2], buffer[3]);
0147 usbnet_ethdev.recv_func (&usbnet_ethdev, buffer, act_len);
0148 }
0149 }
0150 }
0151
0152 static void
0153 irq_loop (void)
0154 {
0155 uint32 tick = 0;
0156 DLOG ("irq_loop pid=0x%x", str ());
0157 for (;;) {
0158 poll ();
0159 DLOG ("iteration %d", tick);
0160 tick++;
0161 }
0162 }
0163
0164 static uint32 irq_stack[1024] ALIGNED(0x1000);
0165 static task_id irq_pid;
0166
0167 static bool
0168 probe (USB_DEVICE_INFO *info, USB_CFG_DESC *cfgd, USB_IF_DESC *ifd)
0169 {
0170 uint i;
0171 uint8 addrstr[13] = { [12] = 0 };
0172 uint8 strbuf[26];
0173 CDC_FUNDESC *fund = (CDC_FUNDESC *)&ifd[1];
0174 CDC_ETHERNET_FUNDESC *ethd;
0175 USB_EPT_DESC *eptd;
0176
0177 if (!(ifd->bInterfaceClass == 0x02 &&
0178 ifd->bInterfaceSubClass == 0x06 &&
0179 ifd->bInterfaceProtocol == 0x00))
0180 return FALSE;
0181
0182 while (fund->bDescriptorType == CDC_TYPE_CS_INTERFACE) {
0183 DLOG ("found functional desc. subtype=0x%x", fund->bDescriptorSubtype);
0184 switch (fund->bDescriptorSubtype) {
0185 case CDC_SUBTYPE_ETHERNET:
0186 ethd = &fund->ethernet;
0187 DLOG ("eth iMAC=%d mss=%d", ethd->iMACAddress, ethd->wMaxSegmentSize);
0188 if (usb_get_descriptor (info, USB_TYPE_STR_DESC, ethd->iMACAddress, 0,
0189 sizeof (strbuf), strbuf) != 0) {
0190 DLOG ("unable to get ethernet address");
0191 return FALSE;
0192 }
0193
0194 for (i=0; i<12; i++)
0195 addrstr[i] = strbuf[2*i+2];
0196 for (i=0; i<6; i++)
0197 ethaddr[i] = hex2byte (&addrstr[2*i]);
0198 DLOG ("ethernet string=%s address=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
0199 addrstr, ethaddr[0], ethaddr[1], ethaddr[2],
0200 ethaddr[3], ethaddr[4], ethaddr[5]);
0201 break;
0202 }
0203 fund = (CDC_FUNDESC *)((uint8 *)fund + fund->bFunctionLength);
0204 }
0205
0206
0207 if (fund->bDescriptorType != USB_TYPE_EPT_DESC) {
0208 DLOG ("did not find Status endpoint: bDescriptorType=0x%x",
0209 fund->bDescriptorType);
0210 return FALSE;
0211 }
0212
0213 eptd = (USB_EPT_DESC *)fund;
0214 status_ept = eptd->bEndpointAddress & 0x7F;
0215 status_maxpkt = eptd->wMaxPacketSize;
0216
0217
0218 ifd = (USB_IF_DESC *) &eptd[1];
0219
0220 if (ifd->bDescriptorType != USB_TYPE_IF_DESC) {
0221 DLOG ("did not find CDC Data (nop): bDescriptorType=0x%x",
0222 ifd->bDescriptorType);
0223 return FALSE;
0224 }
0225
0226 data_iface = ifd->bInterfaceNumber;
0227 data_nop_alt = ifd->bAlternateSetting;
0228
0229
0230 ifd = &ifd[1];
0231
0232 if (ifd->bDescriptorType != USB_TYPE_IF_DESC) {
0233 DLOG ("did not find CDC Data: bDescriptorType=0x%x",
0234 ifd->bDescriptorType);
0235 return FALSE;
0236 }
0237
0238 data_real_alt = ifd->bAlternateSetting;
0239
0240 DLOG ("CDC Data (nop) iface#=%d alt=%d. CDC Data alt=%d",
0241 data_iface, data_nop_alt, data_real_alt);
0242
0243
0244 eptd = (USB_EPT_DESC *) &ifd[1];
0245 data_maxpkt = eptd->wMaxPacketSize;
0246 if (eptd->bEndpointAddress & 0x80)
0247 data_ept_in = eptd->bEndpointAddress & 0x7F;
0248 else
0249 data_ept_out = eptd->bEndpointAddress & 0x7F;
0250
0251 eptd = &eptd[1];
0252 if (data_maxpkt != eptd->wMaxPacketSize) {
0253 DLOG ("cannot handle: in/out packet sizes differ");
0254 return FALSE;
0255 }
0256 if (eptd->bEndpointAddress & 0x80)
0257 data_ept_in = eptd->bEndpointAddress & 0x7F;
0258 else
0259 data_ept_out = eptd->bEndpointAddress & 0x7F;
0260
0261 DLOG ("data_ept_in=%d data_ept_out=%d data_maxpkt=%d",
0262 data_ept_in, data_ept_out, data_maxpkt);
0263 if (usb_set_configuration (info, cfgd->bConfigurationValue) != 0) {
0264 DLOG ("set_configuration: failed");
0265 return FALSE;
0266 }
0267
0268 ethusbdev = info;
0269
0270 if (!reset ())
0271 return FALSE;
0272
0273
0274 usbnet_ethdev.recv_func = NULL;
0275 usbnet_ethdev.send_func = transmit;
0276 usbnet_ethdev.get_hwaddr_func = get_hwaddr;
0277 usbnet_ethdev.poll_func = poll;
0278
0279 if (!net_register_device (&usbnet_ethdev)) {
0280 DLOG ("registration failed");
0281 return FALSE;
0282 }
0283
0284 irq_pid = start_kernel_thread ((uint) irq_loop, (uint) &irq_stack[1023]);
0285
0286 return TRUE;
0287 }
0288
0289 static USB_DRIVER net_driver = {
0290 .probe = probe
0291 };
0292
0293 extern bool
0294 usb_net_driver_init (void)
0295 {
0296 return usb_register_driver (&net_driver);
0297 }
0298
0299 #include "module/header.h"
0300
0301 static const struct module_ops mod_ops = {
0302 .init = usb_net_driver_init
0303 };
0304
0305 DEF_MODULE (usb___net, "USB net driver", &mod_ops, {"usb", "net___ethernet"});
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317