/** * struct ljca_adapter - represent a ljca adapter * * @intf: the usb interface for this ljca adapter * @usb_dev: the usb device for this ljca adapter * @dev: the specific device info of the usb interface * @rx_pipe: bulk in pipe for receive data from firmware * @tx_pipe: bulk out pipe for send data to firmware * @rx_urb: urb used for the bulk in pipe * @rx_buf: buffer used to receive command response and event * @rx_len: length of rx buffer * @ex_buf: external buffer to save command response * @ex_buf_len: length of external buffer * @actual_length: actual length of data copied to external buffer * @tx_buf: buffer used to download command to firmware * @tx_buf_len: length of tx buffer * @lock: spinlock to protect tx_buf and ex_buf * @cmd_completion: completion object as the command receives ack * @mutex: mutex to avoid command download concurrently * @client_list: client device list * @disconnect: usb disconnect ongoing or not * @reset_id: used to reset firmware
*/ struct ljca_adapter { struct usb_interface *intf; struct usb_device *usb_dev; struct device *dev;
list_for_each_entry(client, &adap->client_list, link) { /* * Currently only GPIO register event callback, but * firmware message structure should include id when * multiple same type clients register event callback.
*/ if (client->type == header->type) { unsignedlong flags;
switch (urb->status) { case 0: /* success */ break; case -ENOENT: /* * directly complete the possible ongoing transfer * during disconnect
*/ if (adap->disconnect)
complete(&adap->cmd_completion); return; case -ECONNRESET: case -ESHUTDOWN: case -EPIPE: /* rx urb is terminated */
dev_dbg(adap->dev, "rx urb terminated with status: %d\n",
urb->status); return; default:
dev_dbg(adap->dev, "rx urb error: %d\n", urb->status); goto resubmit;
}
if (header->len + sizeof(*header) != urb->actual_length) goto resubmit;
if (header->flags & LJCA_ACK_FLAG)
ljca_handle_cmd_ack(adap, header); else
ljca_handle_event(adap, header);
resubmit:
ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret && ret != -EPERM)
dev_err(adap->dev, "resubmit rx urb error %d\n", ret);
}
ret = usb_autopm_get_interface(adap->intf); if (ret < 0) goto out;
ret = usb_bulk_msg(adap->usb_dev, adap->tx_pipe, header,
msg_len, &transferred, LJCA_WRITE_TIMEOUT_MS); if (ret < 0) goto out_put; if (transferred != msg_len) {
ret = -EIO; goto out_put;
}
if (ack) {
ret = wait_for_completion_timeout(&adap->cmd_completion,
timeout); if (!ret) {
ret = -ETIMEDOUT; goto out_put;
}
}
ret = adap->actual_length;
if (acpi_match_device_ids(adev, wd->ids)) return 0;
if (!wd->uid) goto match;
if (!uid) /* * Some DSDTs have only one ACPI companion for the two I2C * controllers and they don't set a UID at all (e.g. Dell * Latitude 9420). On these platforms only the first I2C * controller is used, so if a HID match has no UID we use * "0" as the UID and assign ACPI companion to the first * I2C controller.
*/
uid = "0"; else
uid = strchr(uid, wd->uid[0]);
/* construct platform data */
gpio_info = kzalloc(sizeof *gpio_info, GFP_KERNEL); if (!gpio_info) return -ENOMEM;
gpio_info->num = gpio_num;
for (i = 0; i < desc->bank_num; i++)
valid_pin[i] = get_unaligned_le32(&desc->bank_desc[i].valid_pins);
bitmap_from_arr32(gpio_info->valid_pin_map, valid_pin, gpio_num);
/* Not all LJCA chips implement SPI, a timeout reading the descriptors is normal */
ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_SPI, NULL, 0, buf, sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS); if (ret < 0) return (ret == -ETIMEDOUT) ? 0 : ret;
/* * find the first bulk in and out endpoints. * ignore any others.
*/
ret = usb_find_common_endpoints(alt, &ep_in, &ep_out, NULL, NULL); if (ret) {
dev_err(dev, "bulk endpoints not found\n"); goto err_put;
}
adap->rx_pipe = usb_rcvbulkpipe(usb_dev, usb_endpoint_num(ep_in));
adap->tx_pipe = usb_sndbulkpipe(usb_dev, usb_endpoint_num(ep_out));
/* submit rx urb before enumerate clients */
ret = usb_submit_urb(adap->rx_urb, GFP_KERNEL); if (ret) {
dev_err(dev, "submit rx urb failed: %d\n", ret); goto err_free;
}
ret = ljca_enumerate_clients(adap); if (ret) goto err_free;
/* * This works around problems with ov2740 initialization on some * Lenovo platforms. The autosuspend delay, has to be smaller than * the delay after setting the reset_gpio line in ov2740_resume(). * Otherwise the sensor randomly fails to initialize.
*/
pm_runtime_set_autosuspend_delay(&usb_dev->dev, 10);
MODULE_AUTHOR("Wentong Wu ");
MODULE_AUTHOR("Zhifeng Wang ");
MODULE_AUTHOR("Lixu Zhang ");
MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB driver");
MODULE_LICENSE("GPL");
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.