1 #include <errno.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <minix/config.h> 6 #include <minix/const.h> 7 #include <minix/devman.h> 8 #include <minix/usb.h> 9 #include <minix/sysutil.h> 10 11 #include "local.h" 12 13 #define CHECKOUTOFMEM(ptr) if(ptr == NULL) \ 14 panic("Out of memory! (%s, line %d)", \ 15 __FILE__, __LINE__) 16 17 18 static int (*bind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep); 19 static int (*unbind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep); 20 21 /**************************************************************************** 22 * devman_usb_add_attr * 23 ***************************************************************************/ 24 static void 25 devman_usb_add_attr 26 (struct devman_dev *dev, const char *name, const char *data) 27 { 28 struct devman_static_attribute *attr = (struct devman_static_attribute *) 29 malloc(sizeof(struct devman_static_attribute)); 30 31 CHECKOUTOFMEM(attr); 32 33 attr->name = malloc((strlen(name)+1)*sizeof(char)); 34 memcpy(attr->name, name, (strlen(name)+1)); 35 36 attr->data = malloc((strlen(data)+1)*sizeof(char)); 37 memcpy(attr->data, data, (strlen(data)+1)); 38 TAILQ_INSERT_TAIL(&dev->attrs, attr, list); 39 } 40 41 /**************************************************************************** 42 * add_device_attributes * 43 ***************************************************************************/ 44 static void 45 add_device_attributes 46 (struct devman_usb_dev *udev) 47 { 48 int ret; 49 char data[32]; 50 51 ret = snprintf(data,sizeof(data),"0x%02x",udev->desc->bDeviceClass); 52 if (ret < 0) { 53 panic("add_device_attributes: snprintf failed"); 54 } 55 devman_usb_add_attr(udev->dev, "bDeviceClass", data); 56 57 ret = snprintf(data,sizeof(data),"0x%02x",udev->desc->bDeviceSubClass); 58 if (ret < 0) { 59 panic("add_device_attributes: snprintf failed"); 60 } 61 devman_usb_add_attr(udev->dev, "bDeviceSubClass", data); 62 63 ret = snprintf(data,sizeof(data),"0x%02x",udev->desc->bDeviceProtocol); 64 if (ret < 0) { 65 panic("add_device_attributes: snprintf failed"); 66 } 67 devman_usb_add_attr(udev->dev, "bDeviceProtocol", data); 68 69 ret = snprintf(data,sizeof(data),"0x%04x",UGETW(udev->desc->idVendor)); 70 if (ret < 0) { 71 panic("add_device_attributes: snprintf failed"); 72 } 73 devman_usb_add_attr(udev->dev, "idVendor", data); 74 75 ret = snprintf(data,sizeof(data),"0x%04x",UGETW(udev->desc->idProduct)); 76 if (ret < 0) { 77 panic("add_device_attributes: snprintf failed"); 78 } 79 devman_usb_add_attr(udev->dev, "idProduct", data); 80 81 if (udev->product) 82 devman_usb_add_attr(udev->dev, "Product", udev->product); 83 if (udev->manufacturer) 84 devman_usb_add_attr(udev->dev, "Manufacturer", udev->manufacturer); 85 if (udev->serial) 86 devman_usb_add_attr(udev->dev, "SerialNumber", udev->serial); 87 devman_usb_add_attr(udev->dev, "dev_type", "USB_DEV"); 88 } 89 90 /**************************************************************************** 91 * add_interface_attributes * 92 ***************************************************************************/ 93 static void 94 add_interface_attributes 95 (struct devman_usb_interface *intf) 96 { 97 int ret; 98 char data[32]; 99 100 ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceNumber); 101 if (ret < 0) { 102 panic("add_device_attributes: snprintf failed"); 103 } 104 devman_usb_add_attr(intf->dev, "bInterfaceNumber", data); 105 106 ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bAlternateSetting); 107 if (ret < 0) { 108 panic("add_device_attributes: snprintf failed"); 109 } 110 devman_usb_add_attr(intf->dev, "bAlternateSetting", data); 111 112 ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bNumEndpoints); 113 if (ret < 0) { 114 panic("add_device_attributes: snprintf failed"); 115 } 116 devman_usb_add_attr(intf->dev, "bNumEndpoints", data); 117 118 ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceClass); 119 if (ret < 0) { 120 panic("add_device_attributes: snprintf failed"); 121 } 122 devman_usb_add_attr(intf->dev, "bInterfaceClass", data); 123 124 ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceSubClass); 125 if (ret < 0) { 126 panic("add_device_attributes: snprintf failed"); 127 } 128 devman_usb_add_attr(intf->dev, "bInterfaceSubClass", data); 129 130 ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceProtocol); 131 if (ret < 0) { 132 panic("add_device_attributes: snprintf failed"); 133 } 134 devman_usb_add_attr(intf->dev, "bInterfaceProtocol", data); 135 136 devman_usb_add_attr(intf->dev, "dev_type", "USB_INTF"); 137 } 138 139 140 /**************************************************************************** 141 * devman_usb_device_new * 142 ***************************************************************************/ 143 struct devman_usb_dev* 144 devman_usb_device_new 145 (int dev_id) 146 { 147 struct devman_usb_dev *udev = NULL; 148 struct devman_dev * dev = NULL; 149 150 udev = (struct devman_usb_dev *) malloc(sizeof(struct devman_usb_dev)); 151 152 CHECKOUTOFMEM(udev); 153 154 /* allocate device */ 155 dev = (struct devman_dev *) malloc(sizeof(struct devman_dev)); 156 157 CHECKOUTOFMEM(dev); 158 159 udev->dev_id = dev_id; 160 udev->dev = dev; 161 162 dev->parent_dev_id = 0; /* For now add it directly to the root dev */ 163 164 snprintf(dev->name, DEVMAN_DEV_NAME_LEN, "USB%d", dev_id); 165 166 TAILQ_INIT(&dev->attrs); 167 168 return udev; 169 } 170 171 /**************************************************************************** 172 * devman_usb_device_delete * 173 ***************************************************************************/ 174 void devman_usb_device_delete(struct devman_usb_dev *udev) 175 { 176 int i; 177 struct devman_static_attribute *attr,*temp; 178 179 180 for (i=0; i < udev->intf_count; i++) { 181 TAILQ_FOREACH_SAFE(attr, &udev->interfaces[i].dev->attrs, list, temp) 182 { 183 free(attr->name); 184 free(attr->data); 185 free(attr); 186 } 187 free(udev->interfaces[i].dev); 188 } 189 190 TAILQ_FOREACH_SAFE(attr, &udev->dev->attrs, list, temp) { 191 free(attr->name); 192 free(attr->data); 193 free(attr); 194 } 195 196 free(udev->dev); 197 free(udev); 198 } 199 200 static int devman_usb_bind_cb(void *data, endpoint_t ep) { 201 if (bind_cb) { 202 return bind_cb((struct devman_usb_bind_cb_data *) data, ep); 203 } else { 204 return ENODEV; 205 } 206 } 207 208 static int devman_usb_unbind_cb(void *data, endpoint_t ep) { 209 if (unbind_cb) { 210 return unbind_cb((struct devman_usb_bind_cb_data *) data, ep); 211 } else { 212 return ENODEV; 213 } 214 } 215 216 /**************************************************************************** 217 * devman_usb_device_add * 218 ***************************************************************************/ 219 int devman_usb_device_add(struct devman_usb_dev *dev) 220 { 221 int i,res = 0; 222 add_device_attributes(dev); 223 224 /* add the USB device */ 225 dev->cb_data.dev_id = dev->dev_id; 226 dev->cb_data.interface = -1; 227 228 dev->dev->bind_cb = devman_usb_bind_cb; 229 dev->dev->unbind_cb = devman_usb_unbind_cb; 230 dev->dev->data = &dev->cb_data; 231 232 res = devman_add_device(dev->dev); 233 234 if (res != 0) { 235 panic("devman_usb_device_add(): devman_add_device failed."); 236 } 237 238 /* add the USB interfaces */ 239 for (i=0; i < dev->intf_count; i++) { 240 /* prepare */ 241 dev->interfaces[i].dev = 242 (struct devman_dev *) malloc(sizeof(struct devman_dev)); 243 CHECKOUTOFMEM(dev->interfaces[i].dev); 244 245 TAILQ_INIT(&dev->interfaces[i].dev->attrs); 246 snprintf(dev->interfaces[i].dev->name, DEVMAN_DEV_NAME_LEN, 247 "intf%d", i); 248 249 add_interface_attributes(&dev->interfaces[i]); 250 251 dev->interfaces[i].dev->parent_dev_id = dev->dev->dev_id; 252 253 254 dev->interfaces[i].cb_data.dev_id = dev->dev_id; 255 dev->interfaces[i].cb_data.interface = 256 dev->interfaces[i].desc->bInterfaceNumber; 257 258 dev->interfaces[i].dev->bind_cb = devman_usb_bind_cb; 259 dev->interfaces[i].dev->unbind_cb = devman_usb_unbind_cb; 260 dev->interfaces[i].dev->data = &dev->interfaces[i].cb_data; 261 262 /* add */ 263 res = devman_add_device(dev->interfaces[i].dev); 264 265 if (res != 0) { 266 panic("devman_usb_device_add(): devman_add_device failed."); 267 } 268 } 269 270 return res; 271 } 272 273 /**************************************************************************** 274 * devman_usb_device_remove * 275 ***************************************************************************/ 276 int devman_usb_device_remove(struct devman_usb_dev *dev) 277 { 278 int i, res = 0; 279 280 for (i=0; i < dev->intf_count; i++) { 281 282 res = devman_del_device(dev->interfaces[i].dev); 283 284 if (res != 0) { 285 panic("devman_usb_device_remove(): devman_del_device failed."); 286 } 287 } 288 res = devman_del_device(dev->dev); 289 return res; 290 } 291 292 /**************************************************************************** 293 * devman_usb_init * 294 ***************************************************************************/ 295 void devman_usb_init 296 (int (*_bind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep), 297 int (*_unbind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep)) 298 { 299 bind_cb = _bind_cb; 300 unbind_cb = _unbind_cb; 301 } 302