message.c
来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 1,673 行 · 第 1/4 页
C
1,673 行
io->urbs [i]->transfer_dma = sg_dma_address (sg + i); len = sg_dma_len (sg + i); io->urbs[i]->transfer_buffer = page_address(sg[i].page) + sg[i].offset; } else { /* hc may use _only_ transfer_buffer */ io->urbs [i]->transfer_buffer = page_address (sg [i].page) + sg [i].offset; len = sg [i].length; } if (length) { len = min_t (unsigned, len, length); length -= len; if (length == 0) io->entries = i + 1; } io->urbs [i]->transfer_buffer_length = len; } io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT; /* transaction state */ io->status = 0; io->bytes = 0; init_completion (&io->complete); return 0;nomem: sg_clean (io); return -ENOMEM;}/** * usb_sg_wait - synchronously execute scatter/gather request * @io: request block handle, as initialized with usb_sg_init(). * some fields become accessible when this call returns. * Context: !in_interrupt () * * This function blocks until the specified I/O operation completes. It * leverages the grouping of the related I/O requests to get good transfer * rates, by queueing the requests. At higher speeds, such queuing can * significantly improve USB throughput. * * There are three kinds of completion for this function. * (1) success, where io->status is zero. The number of io->bytes * transferred is as requested. * (2) error, where io->status is a negative errno value. The number * of io->bytes transferred before the error is usually less * than requested, and can be nonzero. * (3) cancellation, a type of error with status -ECONNRESET that * is initiated by usb_sg_cancel(). * * When this function returns, all memory allocated through usb_sg_init() or * this call will have been freed. The request block parameter may still be * passed to usb_sg_cancel(), or it may be freed. It could also be * reinitialized and then reused. * * Data Transfer Rates: * * Bulk transfers are valid for full or high speed endpoints. * The best full speed data rate is 19 packets of 64 bytes each * per frame, or 1216 bytes per millisecond. * The best high speed data rate is 13 packets of 512 bytes each * per microframe, or 52 KBytes per millisecond. * * The reason to use interrupt transfers through this API would most likely * be to reserve high speed bandwidth, where up to 24 KBytes per millisecond * could be transferred. That capability is less useful for low or full * speed interrupt endpoints, which allow at most one packet per millisecond, * of at most 8 or 64 bytes (respectively). */void usb_sg_wait (struct usb_sg_request *io){ int i, entries = io->entries; /* queue the urbs. */ spin_lock_irq (&io->lock); for (i = 0; i < entries && !io->status; i++) { int retval; io->urbs [i]->dev = io->dev; retval = usb_submit_urb (io->urbs [i], GFP_ATOMIC); /* after we submit, let completions or cancelations fire; * we handshake using io->status. */ spin_unlock_irq (&io->lock); switch (retval) { /* maybe we retrying will recover */ case -ENXIO: // hc didn't queue this one case -EAGAIN: case -ENOMEM: io->urbs[i]->dev = NULL; retval = 0; i--; yield (); break; /* no error? continue immediately. * * NOTE: to work better with UHCI (4K I/O buffer may * need 3K of TDs) it may be good to limit how many * URBs are queued at once; N milliseconds? */ case 0: cpu_relax (); break; /* fail any uncompleted urbs */ default: io->urbs [i]->dev = NULL; io->urbs [i]->status = retval; dev_dbg (&io->dev->dev, "%s, submit --> %d\n", __FUNCTION__, retval); usb_sg_cancel (io); } spin_lock_irq (&io->lock); if (retval && (io->status == 0 || io->status == -ECONNRESET)) io->status = retval; } io->count -= entries - i; if (io->count == 0) complete (&io->complete); spin_unlock_irq (&io->lock); /* OK, yes, this could be packaged as non-blocking. * So could the submit loop above ... but it's easier to * solve neither problem than to solve both! */ wait_for_completion (&io->complete); sg_clean (io);}/** * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait() * @io: request block, initialized with usb_sg_init() * * This stops a request after it has been started by usb_sg_wait(). * It can also prevents one initialized by usb_sg_init() from starting, * so that call just frees resources allocated to the request. */void usb_sg_cancel (struct usb_sg_request *io){ unsigned long flags; spin_lock_irqsave (&io->lock, flags); /* shut everything down, if it didn't already */ if (!io->status) { int i; io->status = -ECONNRESET; spin_unlock (&io->lock); for (i = 0; i < io->entries; i++) { int retval; if (!io->urbs [i]->dev) continue; retval = usb_unlink_urb (io->urbs [i]); if (retval != -EINPROGRESS && retval != -EBUSY) dev_warn (&io->dev->dev, "%s, unlink --> %d\n", __FUNCTION__, retval); } spin_lock (&io->lock); } spin_unlock_irqrestore (&io->lock, flags);}/*-------------------------------------------------------------------*//** * usb_get_descriptor - issues a generic GET_DESCRIPTOR request * @dev: the device whose descriptor is being retrieved * @type: the descriptor type (USB_DT_*) * @index: the number of the descriptor * @buf: where to put the descriptor * @size: how big is "buf"? * Context: !in_interrupt () * * Gets a USB descriptor. Convenience functions exist to simplify * getting some types of descriptors. Use * usb_get_string() or usb_string() for USB_DT_STRING. * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG) * are part of the device structure. * In addition to a number of USB-standard descriptors, some * devices also use class-specific or vendor-specific descriptors. * * This call is synchronous, and may not be used in an interrupt context. * * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size){ int i; int result; memset(buf,0,size); // Make sure we parse really received data for (i = 0; i < 3; ++i) { /* retry on length 0 or error; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (type << 8) + index, 0, buf, size, USB_CTRL_GET_TIMEOUT); if (result <= 0 && result != -ETIMEDOUT) continue; if (result > 1 && ((u8 *)buf)[1] != type) { result = -EPROTO; continue; } break; } return result;}/** * usb_get_string - gets a string descriptor * @dev: the device whose string descriptor is being retrieved * @langid: code for language chosen (from string descriptor zero) * @index: the number of the descriptor * @buf: where to put the string * @size: how big is "buf"? * Context: !in_interrupt () * * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character, * in little-endian byte order). * The usb_string() function will often be a convenient way to turn * these strings into kernel-printable form. * * Strings may be referenced in device, configuration, interface, or other * descriptors, and could also be used in vendor-specific ways. * * This call is synchronous, and may not be used in an interrupt context. * * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */static int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size){ int i; int result; for (i = 0; i < 3; ++i) { /* retry on length 0 or stall; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (USB_DT_STRING << 8) + index, langid, buf, size, USB_CTRL_GET_TIMEOUT); if (!(result == 0 || result == -EPIPE)) break; } return result;}static void usb_try_string_workarounds(unsigned char *buf, int *length){ int newlength, oldlength = *length; for (newlength = 2; newlength + 1 < oldlength; newlength += 2) if (!isprint(buf[newlength]) || buf[newlength + 1]) break; if (newlength > 2) { buf[0] = newlength; *length = newlength; }}static int usb_string_sub(struct usb_device *dev, unsigned int langid, unsigned int index, unsigned char *buf){ int rc; /* Try to read the string descriptor by asking for the maximum * possible number of bytes */ if (dev->quirks & USB_QUIRK_STRING_FETCH_255) rc = -EIO; else rc = usb_get_string(dev, langid, index, buf, 255); /* If that failed try to read the descriptor length, then * ask for just that many bytes */ if (rc < 2) { rc = usb_get_string(dev, langid, index, buf, 2); if (rc == 2) rc = usb_get_string(dev, langid, index, buf, buf[0]); } if (rc >= 2) { if (!buf[0] && !buf[1]) usb_try_string_workarounds(buf, &rc); /* There might be extra junk at the end of the descriptor */ if (buf[0] < rc) rc = buf[0]; rc = rc - (rc & 1); /* force a multiple of two */ } if (rc < 2) rc = (rc < 0 ? rc : -EINVAL); return rc;}/** * usb_string - returns ISO 8859-1 version of a string descriptor * @dev: the device whose string descriptor is being retrieved * @index: the number of the descriptor * @buf: where to put the string * @size: how big is "buf"? * Context: !in_interrupt () * * This converts the UTF-16LE encoded strings returned by devices, from * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones * that are more usable in most kernel contexts. Note that all characters * in the chosen descriptor that can't be encoded using ISO-8859-1 * are converted to the question mark ("?") character, and this function * chooses strings in the first language supported by the device. * * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, * and is appropriate for use many uses of English and several other * Western European languages. (But it doesn't include the "Euro" symbol.) * * This call is synchronous, and may not be used in an interrupt context. * * Returns length of the string (>= 0) or usb_control_msg status (< 0). */int usb_string(struct usb_device *dev, int index, char *buf, size_t size){ unsigned char *tbuf; int err; unsigned int u, idx; if (dev->state == USB_STATE_SUSPENDED) return -EHOSTUNREACH; if (size <= 0 || !buf || !index) return -EINVAL; buf[0] = 0; tbuf = kmalloc(256, GFP_KERNEL); if (!tbuf) return -ENOMEM; /* get langid for strings if it's not yet known */ if (!dev->have_langid) { err = usb_string_sub(dev, 0, 0, tbuf); if (err < 0) { dev_err (&dev->dev, "string descriptor 0 read error: %d\n", err); goto errout; } else if (err < 4) { dev_err (&dev->dev, "string descriptor 0 too short\n"); err = -EINVAL; goto errout; } else { dev->have_langid = 1; dev->string_langid = tbuf[2] | (tbuf[3]<< 8); /* always use the first langid listed */ dev_dbg (&dev->dev, "default language 0x%04x\n", dev->string_langid); } } err = usb_string_sub(dev, dev->string_langid, index, tbuf); if (err < 0) goto errout; size--; /* leave room for trailing NULL char in output buffer */ for (idx = 0, u = 2; u < err; u += 2) { if (idx >= size) break; if (tbuf[u+1]) /* high byte */ buf[idx++] = '?'; /* non ISO-8859-1 character */ else buf[idx++] = tbuf[u]; } buf[idx] = 0; err = idx; if (tbuf[1] != USB_DT_STRING) dev_dbg(&dev->dev, "wrong descriptor type %02x for string %d (\"%s\")\n", tbuf[1], index, buf); errout: kfree(tbuf); return err;}/** * usb_cache_string - read a string descriptor and cache it for later use * @udev: the device whose string descriptor is being read * @index: the descriptor index * * Returns a pointer to a kmalloc'ed buffer containing the descriptor string, * or NULL if the index is 0 or the string could not be read. */char *usb_cache_string(struct usb_device *udev, int index){ char *buf; char *smallbuf = NULL; int len; if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) { if ((len = usb_string(udev, index, buf, 256)) > 0) { if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL) return buf; memcpy(smallbuf, buf, len); } kfree(buf); } return smallbuf;}/*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?