diff --git a/storage/umass/umass.c b/storage/umass/umass.c index ce31ccd6..503c6ea3 100644 --- a/storage/umass/umass.c +++ b/storage/umass/umass.c @@ -748,7 +748,15 @@ static void umass_msgthr(void *arg) } -static umass_dev_t *umass_devAlloc(void) +static void _umass_devFree(umass_dev_t *dev) +{ + idtree_remove(&umass_common.devices, &dev->node); + resourceDestroy(dev->lock); + free(dev); +} + + +static umass_dev_t *_umass_devAlloc(void) { umass_dev_t *dev; int rv; @@ -769,9 +777,8 @@ static umass_dev_t *umass_devAlloc(void) dev->fileId = idtree_id(&dev->node); rv = snprintf(dev->path, sizeof(dev->path), "/dev/umass%d", dev->fileId); - if (rv < 0) { - resourceDestroy(dev->lock); - free(dev); + if (rv < 0 || rv >= sizeof(dev->path)) { + _umass_devFree(dev); return NULL; } @@ -802,81 +809,89 @@ static int umass_mountRoot(umass_dev_t *dev) } -static int umass_handleInsertion(usb_driver_t *drv, usb_devinfo_t *insertion) +static int umass_handleInsertion(usb_driver_t *drv, usb_devinfo_t *insertion, usb_event_insertion_t *event) { int err; umass_dev_t *dev; oid_t oid; - int ret; - - fprintf(stderr, "umass: pending insertion\n"); mutexLock(umass_common.lock); - if ((dev = umass_devAlloc()) == NULL) { - fprintf(stderr, "umass: devAlloc failed\n"); - return -ENOMEM; - } + do { + dev = _umass_devAlloc(); + if (dev == NULL) { + fprintf(stderr, "umass: devAlloc failed\n"); + err = -ENOMEM; + break; + } - dev->drv = drv; - dev->instance = *insertion; - dev->pipeCtrl = usb_open(drv, insertion, usb_transfer_control, 0); - if (dev->pipeCtrl < 0) { - free(dev); - fprintf(stderr, "umass: usb_open failed\n"); - return -EINVAL; - } + dev->drv = drv; + dev->instance = *insertion; + dev->pipeCtrl = usb_open(drv, insertion, usb_transfer_control, 0); + if (dev->pipeCtrl < 0) { + fprintf(stderr, "umass: usb_open failed\n"); + _umass_devFree(dev); + err = -EINVAL; + break; + } - err = usb_setConfiguration(drv, dev->pipeCtrl, 1); - if (err != 0) { - free(dev); - fprintf(stderr, "umass: setConfiguration failed\n"); - return -EINVAL; - } + err = usb_setConfiguration(drv, dev->pipeCtrl, 1); + if (err != 0) { + fprintf(stderr, "umass: setConfiguration failed\n"); + _umass_devFree(dev); + break; + } - dev->pipeIn = usb_open(drv, insertion, usb_transfer_bulk, usb_dir_in); - if (dev->pipeIn < 0) { - fprintf(stderr, "umass: pipe open failed \n"); - free(dev); - return -EINVAL; - } + dev->pipeIn = usb_open(drv, insertion, usb_transfer_bulk, usb_dir_in); + if (dev->pipeIn < 0) { + fprintf(stderr, "umass: pipe open failed \n"); + _umass_devFree(dev); + err = -EINVAL; + break; + } - dev->pipeOut = usb_open(drv, insertion, usb_transfer_bulk, usb_dir_out); - if (dev->pipeOut < 0) { - fprintf(stderr, "umass: pipe open failed\n"); - free(dev); - return -EINVAL; - } - dev->tag = 0; + dev->pipeOut = usb_open(drv, insertion, usb_transfer_bulk, usb_dir_out); + if (dev->pipeOut < 0) { + fprintf(stderr, "umass: pipe open failed\n"); + _umass_devFree(dev); + err = -EINVAL; + break; + } + dev->tag = 0; - ret = _umass_scsiInit(dev); - if (ret < 0) { - fprintf(stderr, "umass: device didn't initialize properly after scsi init sequence\n"); - free(dev); - return -EINVAL; - } + err = _umass_scsiInit(dev); + if (err < 0) { + fprintf(stderr, "umass: device didn't initialize properly after scsi init sequence\n"); + _umass_devFree(dev); + break; + } - ret = _umass_check(dev); - if (ret < 0) { - fprintf(stderr, "umass: umass_check failed\n"); - free(dev); - return -EINVAL; - } + err = _umass_check(dev); + if (err < 0) { + fprintf(stderr, "umass: umass_check failed\n"); + _umass_devFree(dev); + break; + } - oid.port = umass_common.msgport; - oid.id = dev->fileId; - err = create_dev(&oid, dev->path); - if (err != 0) { - free(dev); - fprintf(stderr, "usb: Can't create dev!\n"); - return -EINVAL; - } + oid.port = umass_common.msgport; + oid.id = dev->fileId; + err = create_dev(&oid, dev->path); + if (err != 0) { + fprintf(stderr, "usb: Can't create dev!\n"); + _umass_devFree(dev); + break; + } - printf("umass: New USB Mass Storage device: %s sectors: %d\n", dev->path, dev->part.sectors); + printf("umass: New USB Mass Storage device: %s sectors: %d\n", dev->path, dev->part.sectors); + + event->deviceCreated = true; + event->dev = oid; + strncpy(event->devPath, dev->path, sizeof(event->devPath)); + } while (0); mutexUnlock(umass_common.lock); - if (umass_common.mount_root) { + if (err == 0 && umass_common.mount_root) { err = umass_mountRoot(dev); if (err < 0) { fprintf(stderr, "umass: failed to mount root partition\n"); @@ -885,7 +900,7 @@ static int umass_handleInsertion(usb_driver_t *drv, usb_devinfo_t *insertion) umass_common.mount_root = false; /* don't try to mount root again */ } - return 0; + return err; } @@ -903,10 +918,9 @@ static int umass_handleDeletion(usb_driver_t *drv, usb_deletion_t *del) dev = lib_treeof(umass_dev_t, node, lib_treeof(idnode_t, linkage, node)); if (dev->instance.bus == del->bus && dev->instance.dev == del->dev && dev->instance.interface == del->interface) { - resourceDestroy(dev->lock); remove(dev->path); fprintf(stderr, "umass: Device removed: %s\n", dev->path); - free(dev); + _umass_devFree(dev); } node = next; diff --git a/tty/usbacm/usbacm.c b/tty/usbacm/usbacm.c index 3979cdaa..3e41486c 100644 --- a/tty/usbacm/usbacm.c +++ b/tty/usbacm/usbacm.c @@ -52,6 +52,10 @@ #define USBACM_UMSG_PRIO 3 #endif +#ifndef USBACM_SET_LINE_DEFAULT_RATE +#define USBACM_SET_LINE_DEFAULT_RATE 57600 +#endif + #define USBACM_BULK_SZ 2048 /* clang-format off */ @@ -91,6 +95,8 @@ typedef struct _usbacm_dev { int rxState; usb_driver_t *drv; + + usb_cdc_line_coding_t line; } usbacm_dev_t; @@ -257,6 +263,20 @@ static void usbacm_put(usbacm_dev_t *dev) } +static int usbacm_setLine(usbacm_dev_t *dev) +{ + usb_setup_packet_t setup = { + .bmRequestType = REQUEST_DIR_HOST2DEV | REQUEST_TYPE_CLASS | REQUEST_RECIPIENT_INTERFACE, + .bRequest = 0x20, /* SET_LINE_CODING */ + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(usb_cdc_line_coding_t), + }; + + return usb_transferControl(dev->drv, dev->pipeCtrl, &setup, &dev->line, sizeof(usb_cdc_line_coding_t), usb_dir_out); +} + + static int usbacm_handleCompletion(usb_driver_t *drv, usb_completion_t *c, const char *data, size_t len) { usbacm_dev_t *dev; @@ -639,7 +659,7 @@ static void usbacm_msgthr(void *arg) } -static int usbacm_handleInsertion(usb_driver_t *drv, usb_devinfo_t *insertion) +static int usbacm_handleInsertion(usb_driver_t *drv, usb_devinfo_t *insertion, usb_event_insertion_t *event) { usbacm_dev_t *dev; const usb_modeswitch_t *mode; @@ -697,13 +717,25 @@ static int usbacm_handleInsertion(usb_driver_t *drv, usb_devinfo_t *insertion) break; } - condCreate(&dev->rxCond); + err = condCreate(&dev->rxCond); if (err != 0) { resourceDestroy(dev->rxLock); err = -ENOMEM; break; } + dev->line.dwDTERate = USBACM_SET_LINE_DEFAULT_RATE; + dev->line.bCharFormat = 0; + dev->line.bParityType = 0; + dev->line.bDataBits = 8; + + /* Some broken devices won't function without doing the set line cmd first */ + err = usbacm_setLine(dev); + if (err < 0) { + fprintf(stderr, "usbacm: Set line to speed %d failed/unsupported: %d\n", dev->line.dwDTERate, err); + /* Continue as this is optional: device may reject the setting/not support the set line cmd */ + } + oid.port = usbacm_common.msgport; oid.id = dev->fileId; @@ -728,6 +760,10 @@ static int usbacm_handleInsertion(usb_driver_t *drv, usb_devinfo_t *insertion) fprintf(stdout, "usbacm: New device: %s\n", dev->path); + event->deviceCreated = true; + event->dev = oid; + strncpy(event->devPath, dev->path, sizeof(event->devPath)); + return 0; }