Commit 0d815142 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (25 commits)
  em28xx: remove backward compat macro added on a previous fix
  V4L/DVB (9748): em28xx: fix compile warning
  V4L/DVB (9743): em28xx: fix oops audio
  V4L/DVB (9742): em28xx-alsa: implement another locking schema
  V4L/DVB (9732): sms1xxx: use new firmware for Hauppauge WinTV MiniStick
  V4L/DVB (9691): gspca: Move the video device to a separate area.
  V4L/DVB (9690): gspca: Lock the subdrivers via module_get/put.
  V4L/DVB (9689): gspca: Memory leak when disconnect while streaming.
  V4L/DVB (9668): em28xx: fix a race condition with hald
  V4L/DVB (9664): af9015: don't reconnect device in USB-bus
  V4L/DVB (9647): em28xx: void having two concurrent control URB's
  V4L/DVB (9646): em28xx: avoid allocating/dealocating memory on every control urb
  V4L/DVB (9645): em28xx: Avoid memory leaks if registration fails
  V4L/DVB (9639): Make dib0700 remote control support work with firmware v1.20
  V4L/DVB (9635): v4l: s2255drv fix firmware test on big-endian
  V4L/DVB (9634): Make sure the i2c gate is open before powering down tuner
  V4L/DVB (9632): make em28xx aux audio input work
  V4L/DVB (9631): Make s2api work for ATSC support
  V4L/DVB (9627): em28xx: Avoid i2c register error for boards without eeprom
  V4L/DVB (9608): Fix section mismatch warning for dm1105 during make
  ...
parents 9c84ba4e a693b0cd
...@@ -376,7 +376,7 @@ static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb) ...@@ -376,7 +376,7 @@ static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr); pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
} }
static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
{ {
outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
outb(1, dm_io_mem(DM1105_CR)); outb(1, dm_io_mem(DM1105_CR));
......
...@@ -585,6 +585,8 @@ static int dvb_frontend_thread(void *data) ...@@ -585,6 +585,8 @@ static int dvb_frontend_thread(void *data)
if (fe->ops.set_voltage) if (fe->ops.set_voltage)
fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
if (fe->ops.tuner_ops.sleep) { if (fe->ops.tuner_ops.sleep) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.sleep(fe); fe->ops.tuner_ops.sleep(fe);
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); fe->ops.i2c_gate_ctrl(fe, 0);
...@@ -934,7 +936,8 @@ void dtv_property_dump(struct dtv_property *tvp) ...@@ -934,7 +936,8 @@ void dtv_property_dump(struct dtv_property *tvp)
int is_legacy_delivery_system(fe_delivery_system_t s) int is_legacy_delivery_system(fe_delivery_system_t s)
{ {
if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
(s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS)) (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) ||
(s == SYS_ATSC))
return 1; return 1;
return 0; return 0;
......
...@@ -681,12 +681,6 @@ static int af9015_download_firmware(struct usb_device *udev, ...@@ -681,12 +681,6 @@ static int af9015_download_firmware(struct usb_device *udev,
goto error; goto error;
} }
/* firmware is running, reconnect device in the usb bus */
req.cmd = RECONNECT_USB;
ret = af9015_rw_udev(udev, &req);
if (ret)
err("reconnect failed: %d", ret);
error: error:
return ret; return ret;
} }
...@@ -1208,6 +1202,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { ...@@ -1208,6 +1202,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.usb_ctrl = DEVICE_SPECIFIC, .usb_ctrl = DEVICE_SPECIFIC,
.download_firmware = af9015_download_firmware, .download_firmware = af9015_download_firmware,
.firmware = "dvb-usb-af9015.fw", .firmware = "dvb-usb-af9015.fw",
.no_reconnect = 1,
.size_of_priv = sizeof(struct af9015_state), \ .size_of_priv = sizeof(struct af9015_state), \
...@@ -1306,6 +1301,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { ...@@ -1306,6 +1301,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.usb_ctrl = DEVICE_SPECIFIC, .usb_ctrl = DEVICE_SPECIFIC,
.download_firmware = af9015_download_firmware, .download_firmware = af9015_download_firmware,
.firmware = "dvb-usb-af9015.fw", .firmware = "dvb-usb-af9015.fw",
.no_reconnect = 1,
.size_of_priv = sizeof(struct af9015_state), \ .size_of_priv = sizeof(struct af9015_state), \
......
...@@ -22,7 +22,7 @@ extern int dvb_usb_dib0700_debug; ...@@ -22,7 +22,7 @@ extern int dvb_usb_dib0700_debug;
#define REQUEST_I2C_READ 0x2 #define REQUEST_I2C_READ 0x2
#define REQUEST_I2C_WRITE 0x3 #define REQUEST_I2C_WRITE 0x3
#define REQUEST_POLL_RC 0x4 #define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */
#define REQUEST_JUMPRAM 0x8 #define REQUEST_JUMPRAM 0x8
#define REQUEST_SET_CLOCK 0xB #define REQUEST_SET_CLOCK 0xB
#define REQUEST_SET_GPIO 0xC #define REQUEST_SET_GPIO 0xC
...@@ -40,11 +40,14 @@ struct dib0700_state { ...@@ -40,11 +40,14 @@ struct dib0700_state {
u16 mt2060_if1[2]; u16 mt2060_if1[2];
u8 rc_toggle; u8 rc_toggle;
u8 rc_counter; u8 rc_counter;
u8 rc_func_version;
u8 is_dib7000pc; u8 is_dib7000pc;
u8 fw_use_new_i2c_api; u8 fw_use_new_i2c_api;
u8 disable_streaming_master_mode; u8 disable_streaming_master_mode;
}; };
extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
u32 *romversion, u32 *ramversion, u32 *fwtype);
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen); extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
......
...@@ -19,6 +19,22 @@ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (defau ...@@ -19,6 +19,22 @@ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (defau
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
u32 *romversion, u32 *ramversion, u32 *fwtype)
{
u8 b[16];
int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
b, sizeof(b), USB_CTRL_GET_TIMEOUT);
*hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
*romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7];
*ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
*fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
return ret;
}
/* expecting rx buffer: request data[0] data[1] ... data[2] */ /* expecting rx buffer: request data[0] data[1] ... data[2] */
static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
{ {
......
...@@ -38,6 +38,7 @@ static struct mt2060_config bristol_mt2060_config[2] = { ...@@ -38,6 +38,7 @@ static struct mt2060_config bristol_mt2060_config[2] = {
} }
}; };
static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = { static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = {
.band_caps = BAND_VHF | BAND_UHF, .band_caps = BAND_VHF | BAND_UHF,
.setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0), .setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0),
...@@ -451,8 +452,13 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; ...@@ -451,8 +452,13 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
/* Number of keypresses to ignore before start repeating */ /* Number of keypresses to ignore before start repeating */
#define RC_REPEAT_DELAY 2 #define RC_REPEAT_DELAY 2
#define RC_REPEAT_DELAY_V1_20 5
static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
/* Used by firmware versions < 1.20 (deprecated) */
static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
int *state)
{ {
u8 key[4]; u8 key[4];
int i; int i;
...@@ -529,6 +535,137 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ...@@ -529,6 +535,137 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0; return 0;
} }
/* This is the structure of the RC response packet starting in firmware 1.20 */
struct dib0700_rc_response {
u8 report_id;
u8 data_state;
u8 system_msb;
u8 system_lsb;
u8 data;
u8 not_data;
};
/* This supports the new IR response format for firmware v1.20 */
static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
int *state)
{
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
struct dib0700_state *st = d->priv;
struct dib0700_rc_response poll_reply;
u8 buf[6];
int i;
int status;
int actlen;
int found = 0;
/* Set initial results in case we exit the function early */
*event = 0;
*state = REMOTE_NO_KEY_PRESSED;
/* Firmware v1.20 provides RC data via bulk endpoint 1 */
status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf,
sizeof(buf), &actlen, 50);
if (status < 0) {
/* No data available (meaning no key press) */
return 0;
}
if (actlen != sizeof(buf)) {
/* We didn't get back the 6 byte message we expected */
err("Unexpected RC response size [%d]", actlen);
return -1;
}
poll_reply.report_id = buf[0];
poll_reply.data_state = buf[1];
poll_reply.system_msb = buf[2];
poll_reply.system_lsb = buf[3];
poll_reply.data = buf[4];
poll_reply.not_data = buf[5];
/*
info("rid=%02x ds=%02x sm=%02x sl=%02x d=%02x nd=%02x\n",
poll_reply.report_id, poll_reply.data_state,
poll_reply.system_msb, poll_reply.system_lsb,
poll_reply.data, poll_reply.not_data);
*/
if ((poll_reply.data + poll_reply.not_data) != 0xff) {
/* Key failed integrity check */
err("key failed integrity check: %02x %02x %02x %02x",
poll_reply.system_msb, poll_reply.system_lsb,
poll_reply.data, poll_reply.not_data);
return -1;
}
/* Find the key in the map */
for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == poll_reply.system_lsb &&
keymap[i].data == poll_reply.data) {
*event = keymap[i].event;
found = 1;
break;
}
}
if (found == 0) {
err("Unknown remote controller key: %02x %02x %02x %02x",
poll_reply.system_msb, poll_reply.system_lsb,
poll_reply.data, poll_reply.not_data);
d->last_event = 0;
return 0;
}
if (poll_reply.data_state == 1) {
/* New key hit */
st->rc_counter = 0;
*event = keymap[i].event;
*state = REMOTE_KEY_PRESSED;
d->last_event = keymap[i].event;
} else if (poll_reply.data_state == 2) {
/* Key repeated */
st->rc_counter++;
/* prevents unwanted double hits */
if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
*event = d->last_event;
*state = REMOTE_KEY_PRESSED;
st->rc_counter = RC_REPEAT_DELAY_V1_20;
}
} else {
err("Unknown data state [%d]", poll_reply.data_state);
}
return 0;
}
static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct dib0700_state *st = d->priv;
/* Because some people may have improperly named firmware files,
let's figure out whether to use the new firmware call or the legacy
call based on the firmware version embedded in the file */
if (st->rc_func_version == 0) {
u32 hwver, romver, ramver, fwtype;
int ret = dib0700_get_version(d, &hwver, &romver, &ramver,
&fwtype);
if (ret < 0) {
err("Could not determine version info");
return -1;
}
if (ramver < 0x10200)
st->rc_func_version = 1;
else
st->rc_func_version = 2;
}
if (st->rc_func_version == 2)
return dib0700_rc_query_v1_20(d, event, state);
else
return dib0700_rc_query_legacy(d, event, state);
}
static struct dvb_usb_rc_key dib0700_rc_keys[] = { static struct dvb_usb_rc_key dib0700_rc_keys[] = {
/* Key codes for the tiny Pinnacle remote*/ /* Key codes for the tiny Pinnacle remote*/
{ 0x07, 0x00, KEY_MUTE }, { 0x07, 0x00, KEY_MUTE },
......
...@@ -135,7 +135,7 @@ stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]) ...@@ -135,7 +135,7 @@ stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num])
static int usb_bulk_urb_init(struct usb_data_stream *stream) static int usb_bulk_urb_init(struct usb_data_stream *stream)
{ {
int i; int i, j;
if ((i = usb_allocate_stream_buffers(stream,stream->props.count, if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
stream->props.u.bulk.buffersize)) < 0) stream->props.u.bulk.buffersize)) < 0)
...@@ -143,9 +143,13 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream) ...@@ -143,9 +143,13 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
/* allocate the URBs */ /* allocate the URBs */
for (i = 0; i < stream->props.count; i++) { for (i = 0; i < stream->props.count; i++) {
if ((stream->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL) stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
if (!stream->urb_list[i]) {
deb_mem("not enough memory for urb_alloc_urb!.\n");
for (j = 0; j < i; j++)
usb_free_urb(stream->urb_list[i]);
return -ENOMEM; return -ENOMEM;
}
usb_fill_bulk_urb( stream->urb_list[i], stream->udev, usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
usb_rcvbulkpipe(stream->udev,stream->props.endpoint), usb_rcvbulkpipe(stream->udev,stream->props.endpoint),
stream->buf_list[i], stream->buf_list[i],
...@@ -170,9 +174,14 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream) ...@@ -170,9 +174,14 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
for (i = 0; i < stream->props.count; i++) { for (i = 0; i < stream->props.count; i++) {
struct urb *urb; struct urb *urb;
int frame_offset = 0; int frame_offset = 0;
if ((stream->urb_list[i] =
usb_alloc_urb(stream->props.u.isoc.framesperurb,GFP_ATOMIC)) == NULL) stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC);
if (!stream->urb_list[i]) {
deb_mem("not enough memory for urb_alloc_urb!\n");
for (j = 0; j < i; j++)
usb_free_urb(stream->urb_list[i]);
return -ENOMEM; return -ENOMEM;
}
urb = stream->urb_list[i]; urb = stream->urb_list[i];
......
...@@ -95,7 +95,7 @@ static struct sms_board sms_boards[] = { ...@@ -95,7 +95,7 @@ static struct sms_board sms_boards[] = {
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
.name = "Hauppauge WinTV MiniStick", .name = "Hauppauge WinTV MiniStick",
.type = SMS_NOVA_B0, .type = SMS_NOVA_B0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw", .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
}, },
}; };
......
...@@ -808,6 +808,12 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) ...@@ -808,6 +808,12 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
ISO_BUF_COUNT, ISO_BUF_COUNT,
&ttusb->iso_dma_handle); &ttusb->iso_dma_handle);
if (!ttusb->iso_buffer) {
dprintk("%s: pci_alloc_consistent - not enough memory\n",
__func__);
return -ENOMEM;
}
memset(ttusb->iso_buffer, 0, memset(ttusb->iso_buffer, 0,
ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT); ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
...@@ -1659,7 +1665,14 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -1659,7 +1665,14 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
ttusb_setup_interfaces(ttusb); ttusb_setup_interfaces(ttusb);
ttusb_alloc_iso_urbs(ttusb); result = ttusb_alloc_iso_urbs(ttusb);
if (result < 0) {
dprintk("%s: ttusb_alloc_iso_urbs - failed\n", __func__);
mutex_unlock(&ttusb->semi2c);
kfree(ttusb);
return result;
}
if (ttusb_init_controller(ttusb)) if (ttusb_init_controller(ttusb))
printk("ttusb_init_controller: error\n"); printk("ttusb_init_controller: error\n");
......
...@@ -1157,6 +1157,12 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) ...@@ -1157,6 +1157,12 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
ISO_BUF_COUNT), ISO_BUF_COUNT),
&dec->iso_dma_handle); &dec->iso_dma_handle);
if (!dec->iso_buffer) {
dprintk("%s: pci_alloc_consistent - not enough memory\n",
__func__);
return -ENOMEM;
}
memset(dec->iso_buffer, 0, memset(dec->iso_buffer, 0,
ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)); ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
...@@ -1254,6 +1260,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec) ...@@ -1254,6 +1260,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE, dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE,
GFP_ATOMIC, &dec->irq_dma_handle); GFP_ATOMIC, &dec->irq_dma_handle);
if(!dec->irq_buffer) { if(!dec->irq_buffer) {
usb_free_urb(dec->irq_urb);
return -ENOMEM; return -ENOMEM;
} }
usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe, usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe,
......
...@@ -62,7 +62,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) ...@@ -62,7 +62,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev)
dprintk("Stopping isoc\n"); dprintk("Stopping isoc\n");
for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
usb_kill_urb(dev->adev->urb[i]); usb_unlink_urb(dev->adev->urb[i]);
usb_free_urb(dev->adev->urb[i]); usb_free_urb(dev->adev->urb[i]);
dev->adev->urb[i] = NULL; dev->adev->urb[i] = NULL;
} }
...@@ -75,7 +75,6 @@ static void em28xx_audio_isocirq(struct urb *urb) ...@@ -75,7 +75,6 @@ static void em28xx_audio_isocirq(struct urb *urb)
struct em28xx *dev = urb->context; struct em28xx *dev = urb->context;
int i; int i;
unsigned int oldptr; unsigned int oldptr;
unsigned long flags;
int period_elapsed = 0; int period_elapsed = 0;
int status; int status;
unsigned char *cp; unsigned char *cp;
...@@ -96,9 +95,21 @@ static void em28xx_audio_isocirq(struct urb *urb) ...@@ -96,9 +95,21 @@ static void em28xx_audio_isocirq(struct urb *urb)
if (!length) if (!length)
continue; continue;
spin_lock_irqsave(&dev->adev->slock, flags);
oldptr = dev->adev->hwptr_done_capture; oldptr = dev->adev->hwptr_done_capture;
if (oldptr + length >= runtime->buffer_size) {
unsigned int cnt =
runtime->buffer_size - oldptr;
memcpy(runtime->dma_area + oldptr * stride, cp,
cnt * stride);
memcpy(runtime->dma_area, cp + cnt * stride,
length * stride - cnt * stride);
} else {
memcpy(runtime->dma_area + oldptr * stride, cp,
length * stride);
}
snd_pcm_stream_lock(substream);
dev->adev->hwptr_done_capture += length; dev->adev->hwptr_done_capture += length;
if (dev->adev->hwptr_done_capture >= if (dev->adev->hwptr_done_capture >=
runtime->buffer_size) runtime->buffer_size)
...@@ -113,19 +124,7 @@ static void em28xx_audio_isocirq(struct urb *urb) ...@@ -113,19 +124,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
period_elapsed = 1; period_elapsed = 1;
} }
spin_unlock_irqrestore(&dev->adev->slock, flags); snd_pcm_stream_unlock(substream);
if (oldptr + length >= runtime->buffer_size) {
unsigned int cnt =
runtime->buffer_size - oldptr;
memcpy(runtime->dma_area + oldptr * stride, cp,
cnt * stride);
memcpy(runtime->dma_area, cp + cnt * stride,
length * stride - cnt * stride);
} else {
memcpy(runtime->dma_area + oldptr * stride, cp,
length * stride);
}
} }
if (period_elapsed) if (period_elapsed)
snd_pcm_period_elapsed(substream); snd_pcm_period_elapsed(substream);
......
...@@ -69,19 +69,33 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, ...@@ -69,19 +69,33 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
int ret, byte; int ret, byte;
if (dev->state & DEV_DISCONNECTED) if (dev->state & DEV_DISCONNECTED)
return(-ENODEV); return -ENODEV;
if (len > URB_MAX_CTRL_SIZE)
return -EINVAL;
em28xx_regdbg("req=%02x, reg=%02x ", req, reg); em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, buf, len, HZ); 0x0000, reg, dev->urb_buf, len, HZ);
if (ret < 0) {
if (reg_debug)
printk(" failed!\n");
mutex_unlock(&dev->ctrl_urb_lock);
return ret;
}
if (len)
memcpy(buf, dev->urb_buf, len);
mutex_unlock(&dev->ctrl_urb_lock);
if (reg_debug) { if (reg_debug) {
printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); printk("%02x values: ", ret);
for (byte = 0; byte < len; byte++) for (byte = 0; byte < len; byte++)
printk(" %02x", (unsigned char)buf[byte]); printk(" %02x", (unsigned char)buf[byte]);
printk("\n"); printk("\n");
} }
...@@ -102,16 +116,20 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) ...@@ -102,16 +116,20 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
em28xx_regdbg("req=%02x, reg=%02x:", req, reg); em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, &val, 1, HZ); 0x0000, reg, dev->urb_buf, 1, HZ);
val = dev->urb_buf[0];
if (reg_debug) mutex_unlock(&dev->ctrl_urb_lock);
printk(ret < 0 ? " failed!\n" :
"%02x\n", (unsigned char) val);
if (ret < 0) if (ret < 0) {
printk(" failed!\n");
return ret; return ret;
}
if (reg_debug)
printk("%02x\n", (unsigned char) val);
return val; return val;
} }
...@@ -130,19 +148,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ...@@ -130,19 +148,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
{ {
int ret; int ret;
/*usb_control_msg seems to expect a kmalloced buffer */
unsigned char *bufs;
if (dev->state & DEV_DISCONNECTED) if (dev->state & DEV_DISCONNECTED)
return -ENODEV; return -ENODEV;
if (len < 1) if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
return -EINVAL; return -EINVAL;
bufs = kmalloc(len, GFP_KERNEL);
em28xx_regdbg("req=%02x reg=%02x:", req, reg); em28xx_regdbg("req=%02x reg=%02x:", req, reg);
if (reg_debug) { if (reg_debug) {
int i; int i;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
...@@ -150,16 +162,16 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ...@@ -150,16 +162,16 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
printk("\n"); printk("\n");
} }
if (!bufs) mutex_lock(&dev->ctrl_urb_lock);
return -ENOMEM; memcpy(dev->urb_buf, buf, len);
memcpy(bufs, buf, len);
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, bufs, len, HZ); 0x0000, reg, dev->urb_buf, len, HZ);
mutex_unlock(&dev->ctrl_urb_lock);
if (dev->wait_after_write) if (dev->wait_after_write)
msleep(dev->wait_after_write); msleep(dev->wait_after_write);
kfree(bufs);
return ret; return ret;
} }
...@@ -270,6 +282,8 @@ static int em28xx_set_audio_source(struct em28xx *dev) ...@@ -270,6 +282,8 @@ static int em28xx_set_audio_source(struct em28xx *dev)
break; break;
case EM28XX_AMUX_LINE_IN: case EM28XX_AMUX_LINE_IN:
input = EM28XX_AUDIO_SRC_LINE; input = EM28XX_AUDIO_SRC_LINE;
video = disable;
line = enable;
break; break;
case EM28XX_AMUX_AC97_VIDEO: case EM28XX_AMUX_AC97_VIDEO:
input = EM28XX_AUDIO_SRC_LINE; input = EM28XX_AUDIO_SRC_LINE;
......
...@@ -337,9 +337,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) ...@@ -337,9 +337,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
/* Check if board has eeprom */ /* Check if board has eeprom */
err = i2c_master_recv(&dev->i2c_client, &buf, 0); err = i2c_master_recv(&dev->i2c_client, &buf, 0);
if (err < 0) { if (err < 0) {
em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n", em28xx_errdev("board has no eeprom\n");
__func__, err); memset(eedata, 0, len);
return err; return -ENODEV;
} }
buf = 0; buf = 0;
...@@ -609,14 +609,16 @@ int em28xx_i2c_register(struct em28xx *dev) ...@@ -609,14 +609,16 @@ int em28xx_i2c_register(struct em28xx *dev)
dev->i2c_client.adapter = &dev->i2c_adap; dev->i2c_client.adapter = &dev->i2c_adap;
retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
if (retval < 0) { if ((retval < 0) && (retval != -ENODEV)) {
em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
__func__, retval); __func__, retval);
return retval; return retval;
} }
if (i2c_scan) if (i2c_scan)
em28xx_do_i2c_scan(dev); em28xx_do_i2c_scan(dev);
return 0; return 0;
} }
......
...@@ -73,6 +73,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); ...@@ -73,6 +73,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static LIST_HEAD(em28xx_devlist); static LIST_HEAD(em28xx_devlist);
static DEFINE_MUTEX(em28xx_devlist_mutex);
static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
...@@ -1519,7 +1520,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) ...@@ -1519,7 +1520,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
struct em28xx_fh *fh; struct em28xx_fh *fh;
enum v4l2_buf_type fh_type = 0; enum v4l2_buf_type fh_type = 0;
lock_kernel(); mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(h, &em28xx_devlist, devlist) { list_for_each_entry(h, &em28xx_devlist, devlist) {
if (h->vdev->minor == minor) { if (h->vdev->minor == minor) {
dev = h; dev = h;
...@@ -1535,10 +1536,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) ...@@ -1535,10 +1536,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
dev = h; dev = h;
} }
} }
if (NULL == dev) { mutex_unlock(&em28xx_devlist_mutex);
unlock_kernel(); if (NULL == dev)
return -ENODEV; return -ENODEV;
}
mutex_lock(&dev->lock);
em28xx_videodbg("open minor=%d type=%s users=%d\n", em28xx_videodbg("open minor=%d type=%s users=%d\n",
minor, v4l2_type_names[fh_type], dev->users); minor, v4l2_type_names[fh_type], dev->users);
...@@ -1547,10 +1549,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) ...@@ -1547,10 +1549,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
if (!fh) { if (!fh) {
em28xx_errdev("em28xx-video.c: Out of memory?!\n"); em28xx_errdev("em28xx-video.c: Out of memory?!\n");
unlock_kernel(); mutex_unlock(&dev->lock);
return -ENOMEM; return -ENOMEM;
} }
mutex_lock(&dev->lock);
fh->dev = dev; fh->dev = dev;
fh->radio = radio; fh->radio = radio;
fh->type = fh_type; fh->type = fh_type;
...@@ -1584,7 +1585,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) ...@@ -1584,7 +1585,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
sizeof(struct em28xx_buffer), fh); sizeof(struct em28xx_buffer), fh);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
unlock_kernel();
return errCode; return errCode;
} }
...@@ -1871,6 +1871,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) ...@@ -1871,6 +1871,7 @@ int em28xx_register_extension(struct em28xx_ops *ops)
{ {
struct em28xx *dev = NULL; struct em28xx *dev = NULL;
mutex_lock(&em28xx_devlist_mutex);
mutex_lock(&em28xx_extension_devlist_lock); mutex_lock(&em28xx_extension_devlist_lock);
list_add_tail(&ops->next, &em28xx_extension_devlist); list_add_tail(&ops->next, &em28xx_extension_devlist);
list_for_each_entry(dev, &em28xx_devlist, devlist) { list_for_each_entry(dev, &em28xx_devlist, devlist) {
...@@ -1879,6 +1880,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) ...@@ -1879,6 +1880,7 @@ int em28xx_register_extension(struct em28xx_ops *ops)
} }
printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
mutex_unlock(&em28xx_extension_devlist_lock); mutex_unlock(&em28xx_extension_devlist_lock);
mutex_unlock(&em28xx_devlist_mutex);
return 0; return 0;
} }
EXPORT_SYMBOL(em28xx_register_extension); EXPORT_SYMBOL(em28xx_register_extension);
...@@ -1887,6 +1889,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) ...@@ -1887,6 +1889,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
{ {
struct em28xx *dev = NULL; struct em28xx *dev = NULL;
mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(dev, &em28xx_devlist, devlist) { list_for_each_entry(dev, &em28xx_devlist, devlist) {
if (dev) if (dev)
ops->fini(dev); ops->fini(dev);
...@@ -1896,6 +1899,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) ...@@ -1896,6 +1899,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
list_del(&ops->next); list_del(&ops->next);
mutex_unlock(&em28xx_extension_devlist_lock); mutex_unlock(&em28xx_extension_devlist_lock);
mutex_unlock(&em28xx_devlist_mutex);
} }
EXPORT_SYMBOL(em28xx_unregister_extension); EXPORT_SYMBOL(em28xx_unregister_extension);
...@@ -1921,6 +1925,60 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, ...@@ -1921,6 +1925,60 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
} }
static int register_analog_devices(struct em28xx *dev)
{
int ret;
/* allocate and fill video video_device struct */
dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
if (!dev->vdev) {
em28xx_errdev("cannot allocate video_device.\n");
return -ENODEV;
}
/* register v4l2 video video_device */
ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
video_nr[dev->devno]);
if (ret) {
em28xx_errdev("unable to register video device (error=%i).\n",
ret);
return ret;
}
/* Allocate and fill vbi video_device struct */
dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi");
/* register v4l2 vbi video_device */
ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
vbi_nr[dev->devno]);
if (ret < 0) {
em28xx_errdev("unable to register vbi device\n");
return ret;
}
if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio");
if (!dev->radio_dev) {
em28xx_errdev("cannot allocate video_device.\n");
return -ENODEV;
}
ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
radio_nr[dev->devno]);
if (ret < 0) {
em28xx_errdev("can't register radio device\n");
return ret;
}
em28xx_info("Registered radio device as /dev/radio%d\n",
dev->radio_dev->num);
}
em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
dev->vdev->num, dev->vbi_dev->num);
return 0;
}
/* /*
* em28xx_init_dev() * em28xx_init_dev()
* allocates and inits the device structs, registers i2c bus and v4l device * allocates and inits the device structs, registers i2c bus and v4l device
...@@ -1936,6 +1994,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, ...@@ -1936,6 +1994,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->udev = udev; dev->udev = udev;
mutex_init(&dev->lock); mutex_init(&dev->lock);
mutex_init(&dev->ctrl_urb_lock);
spin_lock_init(&dev->slock); spin_lock_init(&dev->slock);
init_waitqueue_head(&dev->open); init_waitqueue_head(&dev->open);
init_waitqueue_head(&dev->wait_frame); init_waitqueue_head(&dev->wait_frame);
...@@ -1953,8 +2012,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, ...@@ -1953,8 +2012,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
errCode = em28xx_config(dev); errCode = em28xx_config(dev);
if (errCode) { if (errCode) {
em28xx_errdev("error configuring device\n"); em28xx_errdev("error configuring device\n");
em28xx_devused &= ~(1<<dev->devno);
kfree(dev);
return -ENOMEM; return -ENOMEM;
} }
...@@ -2001,50 +2058,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, ...@@ -2001,50 +2058,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
return errCode; return errCode;
} }
list_add_tail(&dev->devlist, &em28xx_devlist);
/* allocate and fill video video_device struct */
dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
if (NULL == dev->vdev) {
em28xx_errdev("cannot allocate video_device.\n");
goto fail_unreg;
}
/* register v4l2 video video_device */
retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
video_nr[dev->devno]);
if (retval) {
em28xx_errdev("unable to register video device (error=%i).\n",
retval);
goto fail_unreg;
}
/* Allocate and fill vbi video_device struct */
dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi");
/* register v4l2 vbi video_device */
if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
vbi_nr[dev->devno]) < 0) {
em28xx_errdev("unable to register vbi device\n");
retval = -ENODEV;
goto fail_unreg;
}
if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio");
if (NULL == dev->radio_dev) {
em28xx_errdev("cannot allocate video_device.\n");
goto fail_unreg;
}
retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
radio_nr[dev->devno]);
if (retval < 0) {
em28xx_errdev("can't register radio device\n");
goto fail_unreg;
}
em28xx_info("Registered radio device as /dev/radio%d\n",
dev->radio_dev->num);
}
/* init video dma queues */ /* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.active);
INIT_LIST_HEAD(&dev->vidq.queued); INIT_LIST_HEAD(&dev->vidq.queued);
...@@ -2071,8 +2084,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, ...@@ -2071,8 +2084,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
video_mux(dev, 0); video_mux(dev, 0);
em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", mutex_lock(&em28xx_devlist_mutex);
dev->vdev->num, dev->vbi_dev->num); list_add_tail(&dev->devlist, &em28xx_devlist);
retval = register_analog_devices(dev);
if (retval < 0) {
em28xx_release_resources(dev);
mutex_unlock(&em28xx_devlist_mutex);
goto fail_reg_devices;
}
mutex_lock(&em28xx_extension_devlist_lock); mutex_lock(&em28xx_extension_devlist_lock);
if (!list_empty(&em28xx_extension_devlist)) { if (!list_empty(&em28xx_extension_devlist)) {
...@@ -2082,13 +2101,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, ...@@ -2082,13 +2101,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
} }
} }
mutex_unlock(&em28xx_extension_devlist_lock); mutex_unlock(&em28xx_extension_devlist_lock);
mutex_unlock(&em28xx_devlist_mutex);
return 0; return 0;
fail_unreg: fail_reg_devices:
em28xx_release_resources(dev);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
kfree(dev);
return retval; return retval;
} }
...@@ -2231,8 +2249,12 @@ static int em28xx_usb_probe(struct usb_interface *interface, ...@@ -2231,8 +2249,12 @@ static int em28xx_usb_probe(struct usb_interface *interface,
/* allocate device struct */ /* allocate device struct */
retval = em28xx_init_dev(&dev, udev, nr); retval = em28xx_init_dev(&dev, udev, nr);
if (retval) if (retval) {
em28xx_devused &= ~(1<<dev->devno);
kfree(dev);
return retval; return retval;
}
em28xx_info("Found %s\n", em28xx_boards[dev->model].name); em28xx_info("Found %s\n", em28xx_boards[dev->model].name);
......
...@@ -102,6 +102,9 @@ ...@@ -102,6 +102,9 @@
#define EM28XX_MIN_BUF 4 #define EM28XX_MIN_BUF 4
#define EM28XX_DEF_BUF 8 #define EM28XX_DEF_BUF 8
/*Limits the max URB message size */
#define URB_MAX_CTRL_SIZE 80
/* Params for validated field */ /* Params for validated field */
#define EM28XX_BOARD_NOT_VALIDATED 1 #define EM28XX_BOARD_NOT_VALIDATED 1
#define EM28XX_BOARD_VALIDATED 0 #define EM28XX_BOARD_VALIDATED 0
...@@ -430,6 +433,7 @@ struct em28xx { ...@@ -430,6 +433,7 @@ struct em28xx {
/* locks */ /* locks */
struct mutex lock; struct mutex lock;
struct mutex ctrl_urb_lock; /* protects urb_buf */
/* spinlock_t queue_lock; */ /* spinlock_t queue_lock; */
struct list_head inqueue, outqueue; struct list_head inqueue, outqueue;
wait_queue_head_t open, wait_frame, wait_stream; wait_queue_head_t open, wait_frame, wait_stream;
...@@ -451,6 +455,8 @@ struct em28xx { ...@@ -451,6 +455,8 @@ struct em28xx {
unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */
char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */
/* helper funcs that call usb_control_msg */ /* helper funcs that call usb_control_msg */
int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
char *buf, int len); char *buf, int len);
......
...@@ -846,10 +846,13 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -846,10 +846,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0; return 0;
} }
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev)
{ {
int retry = 50; int retry = 50;
if (!gspca_dev->present)
return;
reg_w_val(gspca_dev, 0x0000, 0x00); reg_w_val(gspca_dev, 0x0000, 0x00);
reg_r(gspca_dev, 0x0002, 1); reg_r(gspca_dev, 0x0002, 1);
reg_w_val(gspca_dev, 0x0053, 0x00); reg_w_val(gspca_dev, 0x0053, 0x00);
......
...@@ -276,6 +276,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ...@@ -276,6 +276,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
/* Stop the state machine */ /* Stop the state machine */
if (dev->state != FPIX_NOP) if (dev->state != FPIX_NOP)
wait_for_completion(&dev->can_close); wait_for_completion(&dev->can_close);
}
/* called on streamoff with alt 0 and disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
usb_free_urb(dev->control_urb); usb_free_urb(dev->control_urb);
dev->control_urb = NULL; dev->control_urb = NULL;
...@@ -385,6 +391,7 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -385,6 +391,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
error: error:
/* Free the ressources */ /* Free the ressources */
sd_stopN(gspca_dev); sd_stopN(gspca_dev);
sd_stop0(gspca_dev);
return ret; return ret;
} }
...@@ -425,6 +432,7 @@ static const struct sd_desc sd_desc = { ...@@ -425,6 +432,7 @@ static const struct sd_desc sd_desc = {
.init = sd_init, .init = sd_init,
.start = sd_start, .start = sd_start,
.stopN = sd_stopN, .stopN = sd_stopN,
.stop0 = sd_stop0,
}; };
/* -- device connect -- */ /* -- device connect -- */
......
...@@ -646,15 +646,14 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) ...@@ -646,15 +646,14 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
{ {
gspca_dev->streaming = 0; gspca_dev->streaming = 0;
atomic_set(&gspca_dev->nevent, 0); atomic_set(&gspca_dev->nevent, 0);
if (gspca_dev->present) { if (gspca_dev->present
if (gspca_dev->sd_desc->stopN) && gspca_dev->sd_desc->stopN)
gspca_dev->sd_desc->stopN(gspca_dev); gspca_dev->sd_desc->stopN(gspca_dev);
destroy_urbs(gspca_dev); destroy_urbs(gspca_dev);
gspca_set_alt0(gspca_dev); gspca_set_alt0(gspca_dev);
if (gspca_dev->sd_desc->stop0) if (gspca_dev->sd_desc->stop0)
gspca_dev->sd_desc->stop0(gspca_dev); gspca_dev->sd_desc->stop0(gspca_dev);
PDEBUG(D_STREAM, "stream off OK"); PDEBUG(D_STREAM, "stream off OK");
}
} }
static void gspca_set_default_mode(struct gspca_dev *gspca_dev) static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
...@@ -863,7 +862,7 @@ static int dev_open(struct inode *inode, struct file *file) ...@@ -863,7 +862,7 @@ static int dev_open(struct inode *inode, struct file *file)
int ret; int ret;
PDEBUG(D_STREAM, "%s open", current->comm); PDEBUG(D_STREAM, "%s open", current->comm);
gspca_dev = (struct gspca_dev *) video_devdata(file); gspca_dev = video_drvdata(file);
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
if (!gspca_dev->present) { if (!gspca_dev->present) {
...@@ -875,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file) ...@@ -875,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file)
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
/* protect the subdriver against rmmod */
if (!try_module_get(gspca_dev->module)) {
ret = -ENODEV;
goto out;
}
gspca_dev->users++; gspca_dev->users++;
/* one more user */ /* one more user */
...@@ -884,10 +890,10 @@ static int dev_open(struct inode *inode, struct file *file) ...@@ -884,10 +890,10 @@ static int dev_open(struct inode *inode, struct file *file)
#ifdef GSPCA_DEBUG #ifdef GSPCA_DEBUG
/* activate the v4l2 debug */ /* activate the v4l2 debug */
if (gspca_debug & D_V4L2) if (gspca_debug & D_V4L2)
gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL gspca_dev->vdev->debug |= V4L2_DEBUG_IOCTL
| V4L2_DEBUG_IOCTL_ARG; | V4L2_DEBUG_IOCTL_ARG;
else else
gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL gspca_dev->vdev->debug &= ~(V4L2_DEBUG_IOCTL
| V4L2_DEBUG_IOCTL_ARG); | V4L2_DEBUG_IOCTL_ARG);
#endif #endif
ret = 0; ret = 0;
...@@ -921,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file) ...@@ -921,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file)
gspca_dev->memory = GSPCA_MEMORY_NO; gspca_dev->memory = GSPCA_MEMORY_NO;
} }
file->private_data = NULL; file->private_data = NULL;
module_put(gspca_dev->module);
mutex_unlock(&gspca_dev->queue_lock); mutex_unlock(&gspca_dev->queue_lock);
PDEBUG(D_STREAM, "close done"); PDEBUG(D_STREAM, "close done");
...@@ -1748,11 +1755,6 @@ static ssize_t dev_read(struct file *file, char __user *data, ...@@ -1748,11 +1755,6 @@ static ssize_t dev_read(struct file *file, char __user *data,
return ret; return ret;
} }
static void dev_release(struct video_device *vfd)
{
/* nothing */
}
static struct file_operations dev_fops = { static struct file_operations dev_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = dev_open, .open = dev_open,
...@@ -1800,7 +1802,7 @@ static struct video_device gspca_template = { ...@@ -1800,7 +1802,7 @@ static struct video_device gspca_template = {
.name = "gspca main driver", .name = "gspca main driver",
.fops = &dev_fops, .fops = &dev_fops,
.ioctl_ops = &dev_ioctl_ops, .ioctl_ops = &dev_ioctl_ops,
.release = dev_release, /* mandatory */ .release = video_device_release,
.minor = -1, .minor = -1,
}; };
...@@ -1869,17 +1871,18 @@ int gspca_dev_probe(struct usb_interface *intf, ...@@ -1869,17 +1871,18 @@ int gspca_dev_probe(struct usb_interface *intf,
init_waitqueue_head(&gspca_dev->wq); init_waitqueue_head(&gspca_dev->wq);
/* init video stuff */ /* init video stuff */
memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); gspca_dev->vdev = video_device_alloc();
gspca_dev->vdev.parent = &dev->dev; memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template);
memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops); gspca_dev->vdev->parent = &dev->dev;
gspca_dev->vdev.fops = &gspca_dev->fops; gspca_dev->module = module;
gspca_dev->fops.owner = module; /* module protection */
gspca_dev->present = 1; gspca_dev->present = 1;
ret = video_register_device(&gspca_dev->vdev, video_set_drvdata(gspca_dev->vdev, gspca_dev);
ret = video_register_device(gspca_dev->vdev,
VFL_TYPE_GRABBER, VFL_TYPE_GRABBER,
video_nr); video_nr);
if (ret < 0) { if (ret < 0) {
err("video_register_device err %d", ret); err("video_register_device err %d", ret);
video_device_release(gspca_dev->vdev);
goto out; goto out;
} }
...@@ -1887,7 +1890,8 @@ int gspca_dev_probe(struct usb_interface *intf, ...@@ -1887,7 +1890,8 @@ int gspca_dev_probe(struct usb_interface *intf,
PDEBUG(D_PROBE, "probe ok"); PDEBUG(D_PROBE, "probe ok");
return 0; return 0;
out: out:
kref_put(&gspca_dev->kref, gspca_delete); kfree(gspca_dev->usb_buf);
kfree(gspca_dev);
return ret; return ret;
} }
EXPORT_SYMBOL(gspca_dev_probe); EXPORT_SYMBOL(gspca_dev_probe);
...@@ -1905,7 +1909,7 @@ void gspca_disconnect(struct usb_interface *intf) ...@@ -1905,7 +1909,7 @@ void gspca_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
/* We don't want people trying to open up the device */ /* We don't want people trying to open up the device */
video_unregister_device(&gspca_dev->vdev); video_unregister_device(gspca_dev->vdev);
gspca_dev->present = 0; gspca_dev->present = 0;
gspca_dev->streaming = 0; gspca_dev->streaming = 0;
......
...@@ -97,7 +97,7 @@ struct sd_desc { ...@@ -97,7 +97,7 @@ struct sd_desc {
cam_pkt_op pkt_scan; cam_pkt_op pkt_scan;
/* optional operations */ /* optional operations */
cam_v_op stopN; /* called on stream off - main alt */ cam_v_op stopN; /* called on stream off - main alt */
cam_v_op stop0; /* called on stream off - alt 0 */ cam_v_op stop0; /* called on stream off & disconnect - alt 0 */
cam_v_op dq_callback; /* called when a frame has been dequeued */ cam_v_op dq_callback; /* called when a frame has been dequeued */
cam_jpg_op get_jcomp; cam_jpg_op get_jcomp;
cam_jpg_op set_jcomp; cam_jpg_op set_jcomp;
...@@ -120,8 +120,8 @@ struct gspca_frame { ...@@ -120,8 +120,8 @@ struct gspca_frame {
}; };
struct gspca_dev { struct gspca_dev {
struct video_device vdev; /* !! must be the first item */ struct video_device *vdev;
struct file_operations fops; struct module *module; /* subdriver handling the device */
struct usb_device *dev; struct usb_device *dev;
struct kref kref; struct kref kref;
struct file *capt_file; /* file doing video capture */ struct file *capt_file; /* file doing video capture */
......
...@@ -749,10 +749,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ...@@ -749,10 +749,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
} }
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
if (!gspca_dev->present)
return;
if (sd->sensor == SENSOR_PAC7302) { if (sd->sensor == SENSOR_PAC7302) {
reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x40); reg_w(gspca_dev, 0x78, 0x40);
......
...@@ -2022,8 +2022,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ...@@ -2022,8 +2022,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00); reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
} }
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev)
{ {
if (!gspca_dev->present)
return;
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00); reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
} }
......
...@@ -742,8 +742,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ...@@ -742,8 +742,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_write(gspca_dev->dev, 0x02, 0x00, 0x00); reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
} }
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev)
{ {
if (!gspca_dev->present)
return;
/* This maybe reset or power control */ /* This maybe reset or power control */
reg_write(gspca_dev->dev, 0x03, 0x03, 0x20); reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
reg_write(gspca_dev->dev, 0x03, 0x01, 0x0); reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
......
...@@ -766,10 +766,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ...@@ -766,10 +766,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
} }
} }
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
if (!gspca_dev->present)
return;
if (sd->chip_revision == Rev012A) { if (sd->chip_revision == Rev012A) {
reg_w_val(gspca_dev->dev, 0x8118, 0x29); reg_w_val(gspca_dev->dev, 0x8118, 0x29);
reg_w_val(gspca_dev->dev, 0x8114, 0x08); reg_w_val(gspca_dev->dev, 0x8114, 0x08);
......
...@@ -1633,10 +1633,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ...@@ -1633,10 +1633,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(dev, 0xa0, 0x09, 0xb003); reg_w(dev, 0xa0, 0x09, 0xb003);
} }
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev)
{ {
struct usb_device *dev = gspca_dev->dev; struct usb_device *dev = gspca_dev->dev;
if (!gspca_dev->present)
return;
reg_w(dev, 0x89, 0xffff, 0xffff); reg_w(dev, 0x89, 0xffff, 0xffff);
} }
......
...@@ -7336,10 +7336,13 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -7336,10 +7336,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0; return 0;
} }
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
if (!gspca_dev->present)
return;
send_unknown(gspca_dev->dev, sd->sensor); send_unknown(gspca_dev->dev, sd->sensor);
} }
......
...@@ -192,7 +192,7 @@ struct s2255_dmaqueue { ...@@ -192,7 +192,7 @@ struct s2255_dmaqueue {
#define S2255_FW_FAILED 3 #define S2255_FW_FAILED 3
#define S2255_FW_DISCONNECTING 4 #define S2255_FW_DISCONNECTING 4
#define S2255_FW_MARKER 0x22552f2f #define S2255_FW_MARKER cpu_to_le32(0x22552f2f)
/* 2255 read states */ /* 2255 read states */
#define S2255_READ_IDLE 0 #define S2255_READ_IDLE 0
#define S2255_READ_FRAME 1 #define S2255_READ_FRAME 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment